@bodhiapp/bodhi-js-ext 0.0.31 → 0.0.32
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 +528 -434
- package/dist/chrome-storage.d.ts +6 -0
- package/dist/constants.d.ts +6 -0
- package/dist/direct-client.d.ts +3 -6
- package/dist/ext-client.d.ts +6 -1
- package/dist/ext2ext-client.d.ts +20 -5
- package/dist/facade-client.d.ts +5 -1
- package/dist/index.d.ts +3 -0
- package/dist/messages.d.ts +47 -0
- package/package.json +4 -4
package/dist/bodhi-ext.esm.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { DirectClientBase as
|
|
2
|
-
import {
|
|
1
|
+
import { DirectClientBase as $, createStoragePrefixWithBasePath as X, STORAGE_PREFIXES as N, AccessRequestBuilder as v, unwrapResponse as L, DEFAULT_POLL_TIMEOUT_MS as P, DEFAULT_POLL_INTERVAL_MS as b, createOperationError as l, generateCodeVerifier as A, generateCodeChallenge as B, PENDING_EXTENSION_READY as f, Logger as x, NOOP_STATE_CALLBACK as V, createExtensionStateNotInitialized as z, BACKEND_SERVER_NOT_REACHABLE as K, createExtensionStateNotFound as F, BodhiError as T, INITIAL_AUTH_STATE as G, BodhiApiError as Q, Chat as H, Models as W, Embeddings as J, Mcps as Y, pollAccessRequestUntilResolved as k, isAuthError as Z, BaseFacadeClient as j, refreshAccessToken as ee } from "@bodhiapp/bodhi-js-core";
|
|
2
|
+
import { InMemoryStorage as Ce } from "@bodhiapp/bodhi-js-core";
|
|
3
|
+
import { isExtError as I, isApiSuccessResponse as te, MESSAGE_TYPES as _, EXT_ACTIONS as re, BODHI_STREAM_PORT as se, isStreamChunk as oe, isStreamApiError as ne, isStreamError as ie, BODHI_STREAM_TEXT_PORT as ae } from "@bodhiapp/bodhi-browser-types";
|
|
3
4
|
const c = {
|
|
4
5
|
EXT2EXT_CLIENT_REQUEST: "EXT2EXT_CLIENT_REQUEST",
|
|
5
6
|
EXT2EXT_CLIENT_RESPONSE: "EXT2EXT_CLIENT_RESPONSE",
|
|
@@ -11,32 +12,52 @@ const c = {
|
|
|
11
12
|
EXT2EXT_CLIENT_STREAM_CHUNK: "EXT2EXT_CLIENT_STREAM_CHUNK",
|
|
12
13
|
EXT2EXT_CLIENT_STREAM_ERROR: "EXT2EXT_CLIENT_STREAM_ERROR",
|
|
13
14
|
EXT2EXT_CLIENT_STREAM_API_ERROR: "EXT2EXT_CLIENT_STREAM_API_ERROR",
|
|
14
|
-
EXT2EXT_CLIENT_STREAM_DONE: "EXT2EXT_CLIENT_STREAM_DONE"
|
|
15
|
-
|
|
15
|
+
EXT2EXT_CLIENT_STREAM_DONE: "EXT2EXT_CLIENT_STREAM_DONE",
|
|
16
|
+
// Stream text message types (raw text streaming, no SSE/JSON parsing)
|
|
17
|
+
EXT2EXT_CLIENT_STREAM_TEXT_REQUEST: "EXT2EXT_CLIENT_STREAM_TEXT_REQUEST",
|
|
18
|
+
EXT2EXT_CLIENT_STREAM_TEXT_START: "EXT2EXT_CLIENT_STREAM_TEXT_START",
|
|
19
|
+
EXT2EXT_CLIENT_STREAM_TEXT_CHUNK: "EXT2EXT_CLIENT_STREAM_TEXT_CHUNK",
|
|
20
|
+
EXT2EXT_CLIENT_STREAM_TEXT_DONE: "EXT2EXT_CLIENT_STREAM_TEXT_DONE",
|
|
21
|
+
EXT2EXT_CLIENT_STREAM_TEXT_ERROR: "EXT2EXT_CLIENT_STREAM_TEXT_ERROR"
|
|
22
|
+
}, M = "ext2ext-client-stream", O = "ext2ext-client-stream-text", p = {
|
|
16
23
|
LOGIN: "login",
|
|
17
24
|
LOGOUT: "logout",
|
|
18
25
|
GET_AUTH_STATE: "getAuthState",
|
|
19
26
|
DISCOVER_EXTENSION: "discoverBodhiExtension",
|
|
20
27
|
GET_EXTENSION_ID: "get_extension_id",
|
|
21
28
|
SET_EXTENSION_ID: "setExtensionId"
|
|
22
|
-
},
|
|
23
|
-
function
|
|
24
|
-
return "error" in
|
|
29
|
+
}, ce = 5e3, he = 3, Ee = 500, ue = 500, de = 3e4;
|
|
30
|
+
function le(R) {
|
|
31
|
+
return "error" in R;
|
|
25
32
|
}
|
|
26
|
-
class
|
|
33
|
+
class Te {
|
|
34
|
+
async get(e) {
|
|
35
|
+
const r = (await chrome.storage.session.get(e))[e];
|
|
36
|
+
return r !== void 0 ? String(r) : null;
|
|
37
|
+
}
|
|
38
|
+
async set(e) {
|
|
39
|
+
await chrome.storage.session.set(e);
|
|
40
|
+
}
|
|
41
|
+
async remove(e) {
|
|
42
|
+
await chrome.storage.session.remove(e);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
class ge extends $ {
|
|
27
46
|
constructor(e, t) {
|
|
28
|
-
const r =
|
|
47
|
+
const r = X(
|
|
29
48
|
e.basePath,
|
|
30
|
-
|
|
31
|
-
),
|
|
49
|
+
N.EXT_DIRECT
|
|
50
|
+
), n = {
|
|
32
51
|
authClientId: e.authClientId,
|
|
33
52
|
authServerUrl: e.authServerUrl,
|
|
34
53
|
storagePrefix: r,
|
|
35
54
|
logLevel: e.logLevel,
|
|
36
55
|
loggerPrefix: "DirectExtClient",
|
|
37
|
-
apiTimeoutMs: e.apiTimeoutMs
|
|
56
|
+
apiTimeoutMs: e.apiTimeoutMs,
|
|
57
|
+
storage: e.storage ?? new Te(),
|
|
58
|
+
initialTokens: e.initialTokens
|
|
38
59
|
};
|
|
39
|
-
super(
|
|
60
|
+
super(n, t);
|
|
40
61
|
}
|
|
41
62
|
// ============================================================================
|
|
42
63
|
// Authentication (chrome.identity OAuth)
|
|
@@ -48,163 +69,72 @@ class ue extends M {
|
|
|
48
69
|
e?.flowType === "redirect" && this.logger.warn("Extension mode does not support redirect flow type; using popup instead");
|
|
49
70
|
const r = e?.userRole ?? "scope_user_user";
|
|
50
71
|
e?.onProgress?.("requesting");
|
|
51
|
-
const
|
|
52
|
-
e?.requested &&
|
|
53
|
-
const o =
|
|
72
|
+
const n = new v(this.authClientId).requestedRole(r).flowType("popup");
|
|
73
|
+
e?.requested && n.requested(e.requested);
|
|
74
|
+
const o = n.build(), s = await this.requestAccess(o), { id: i, review_url: h } = L(s);
|
|
54
75
|
e?.onProgress?.("reviewing"), await chrome.tabs.create({ url: h });
|
|
55
|
-
const a = await this.pollAccessRequestStatus(
|
|
56
|
-
intervalMs: e?.pollIntervalMs ??
|
|
57
|
-
timeoutMs: e?.pollTimeoutMs ??
|
|
76
|
+
const a = await this.pollAccessRequestStatus(i, {
|
|
77
|
+
intervalMs: e?.pollIntervalMs ?? b,
|
|
78
|
+
timeoutMs: e?.pollTimeoutMs ?? P
|
|
58
79
|
});
|
|
59
80
|
if (a.status !== "approved")
|
|
60
81
|
throw l("auth_error", `Access request ${a.status}`);
|
|
61
|
-
const
|
|
62
|
-
return e?.onProgress?.("authenticating"), this.performOAuthPkce(`openid profile email roles ${
|
|
82
|
+
const E = a.access_request_scope;
|
|
83
|
+
return e?.onProgress?.("authenticating"), this.performOAuthPkce(`openid profile email roles ${E ?? ""}`.trim());
|
|
63
84
|
}
|
|
64
85
|
async performOAuthPkce(e) {
|
|
65
|
-
const t =
|
|
66
|
-
await
|
|
86
|
+
const t = A(), r = await B(t), n = A();
|
|
87
|
+
await this._storageSet({
|
|
67
88
|
[this.storageKeys.CODE_VERIFIER]: t,
|
|
68
|
-
[this.storageKeys.STATE]:
|
|
89
|
+
[this.storageKeys.STATE]: n
|
|
69
90
|
});
|
|
70
91
|
const o = chrome.identity.getRedirectURL("callback"), s = new URL(this.authEndpoints.authorize);
|
|
71
|
-
return s.searchParams.set("client_id", this.authClientId), s.searchParams.set("response_type", "code"), s.searchParams.set("redirect_uri", o), s.searchParams.set("scope", e), s.searchParams.set("code_challenge", r), s.searchParams.set("code_challenge_method", "S256"), s.searchParams.set("state",
|
|
92
|
+
return s.searchParams.set("client_id", this.authClientId), s.searchParams.set("response_type", "code"), s.searchParams.set("redirect_uri", o), s.searchParams.set("scope", e), s.searchParams.set("code_challenge", r), s.searchParams.set("code_challenge_method", "S256"), s.searchParams.set("state", n), new Promise((i, h) => {
|
|
72
93
|
chrome.identity.launchWebAuthFlow(
|
|
73
94
|
{ url: s.toString(), interactive: !0 },
|
|
74
95
|
async (a) => {
|
|
75
96
|
if (chrome.runtime.lastError) {
|
|
76
|
-
await
|
|
77
|
-
this.storageKeys.CODE_VERIFIER,
|
|
78
|
-
this.storageKeys.STATE
|
|
79
|
-
]), h(chrome.runtime.lastError);
|
|
97
|
+
await this._storageRemove([this.storageKeys.CODE_VERIFIER, this.storageKeys.STATE]), h(chrome.runtime.lastError);
|
|
80
98
|
return;
|
|
81
99
|
}
|
|
82
100
|
if (!a) {
|
|
83
|
-
await
|
|
84
|
-
this.storageKeys.CODE_VERIFIER,
|
|
85
|
-
this.storageKeys.STATE
|
|
86
|
-
]), h(l("oauth_error", "No redirect URL received"));
|
|
101
|
+
await this._storageRemove([this.storageKeys.CODE_VERIFIER, this.storageKeys.STATE]), h(l("oauth_error", "No redirect URL received"));
|
|
87
102
|
return;
|
|
88
103
|
}
|
|
89
104
|
try {
|
|
90
|
-
const
|
|
91
|
-
if (
|
|
92
|
-
await
|
|
93
|
-
this.storageKeys.CODE_VERIFIER,
|
|
94
|
-
this.storageKeys.STATE
|
|
95
|
-
]), h(l("oauth_error", "State mismatch"));
|
|
105
|
+
const E = new URL(a), d = E.searchParams.get("code"), u = E.searchParams.get("state"), g = await this._storageGet(this.storageKeys.STATE);
|
|
106
|
+
if (u !== g) {
|
|
107
|
+
await this._storageRemove([this.storageKeys.CODE_VERIFIER, this.storageKeys.STATE]), h(l("oauth_error", "State mismatch"));
|
|
96
108
|
return;
|
|
97
109
|
}
|
|
98
110
|
if (!d) {
|
|
99
|
-
await
|
|
100
|
-
this.storageKeys.CODE_VERIFIER,
|
|
101
|
-
this.storageKeys.STATE
|
|
102
|
-
]), h(l("oauth_error", "No authorization code"));
|
|
111
|
+
await this._storageRemove([this.storageKeys.CODE_VERIFIER, this.storageKeys.STATE]), h(l("oauth_error", "No authorization code"));
|
|
103
112
|
return;
|
|
104
113
|
}
|
|
105
114
|
await this.exchangeCodeForTokens(d);
|
|
106
|
-
const
|
|
107
|
-
if (
|
|
115
|
+
const m = await this.getAuthState();
|
|
116
|
+
if (m.status !== "authenticated")
|
|
108
117
|
throw l("oauth_error", "Login failed");
|
|
109
|
-
this.setAuthState(
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
]), n(E);
|
|
113
|
-
} catch (u) {
|
|
114
|
-
await chrome.storage.session.remove([
|
|
115
|
-
this.storageKeys.CODE_VERIFIER,
|
|
116
|
-
this.storageKeys.STATE
|
|
117
|
-
]), h(u);
|
|
118
|
+
this.setAuthState(m), await this._storageRemove([this.storageKeys.CODE_VERIFIER, this.storageKeys.STATE]), i(m);
|
|
119
|
+
} catch (E) {
|
|
120
|
+
await this._storageRemove([this.storageKeys.CODE_VERIFIER, this.storageKeys.STATE]), h(E);
|
|
118
121
|
}
|
|
119
122
|
}
|
|
120
123
|
);
|
|
121
124
|
});
|
|
122
125
|
}
|
|
123
|
-
async logout() {
|
|
124
|
-
const t = (await chrome.storage.session.get(this.storageKeys.REFRESH_TOKEN))[this.storageKeys.REFRESH_TOKEN];
|
|
125
|
-
if (t)
|
|
126
|
-
try {
|
|
127
|
-
const i = new URLSearchParams({
|
|
128
|
-
token: t,
|
|
129
|
-
client_id: this.authClientId,
|
|
130
|
-
token_type_hint: "refresh_token"
|
|
131
|
-
});
|
|
132
|
-
await fetch(this.authEndpoints.revoke, {
|
|
133
|
-
method: "POST",
|
|
134
|
-
headers: {
|
|
135
|
-
"Content-Type": "application/x-www-form-urlencoded"
|
|
136
|
-
},
|
|
137
|
-
body: i
|
|
138
|
-
});
|
|
139
|
-
} catch (i) {
|
|
140
|
-
this.logger.warn("Token revocation failed:", i);
|
|
141
|
-
}
|
|
142
|
-
await chrome.storage.session.remove([
|
|
143
|
-
this.storageKeys.ACCESS_TOKEN,
|
|
144
|
-
this.storageKeys.REFRESH_TOKEN,
|
|
145
|
-
this.storageKeys.EXPIRES_AT
|
|
146
|
-
]);
|
|
147
|
-
const r = {
|
|
148
|
-
status: "unauthenticated",
|
|
149
|
-
user: null,
|
|
150
|
-
accessToken: null,
|
|
151
|
-
error: null
|
|
152
|
-
};
|
|
153
|
-
return this.setAuthState(r), r;
|
|
154
|
-
}
|
|
155
|
-
// ============================================================================
|
|
156
|
-
// OAuth Helper Methods
|
|
157
|
-
// ============================================================================
|
|
158
|
-
async exchangeCodeForTokens(e) {
|
|
159
|
-
const r = (await chrome.storage.session.get(this.storageKeys.CODE_VERIFIER))[this.storageKeys.CODE_VERIFIER], i = chrome.identity.getRedirectURL("callback"), o = await fetch(this.authEndpoints.token, {
|
|
160
|
-
method: "POST",
|
|
161
|
-
headers: {
|
|
162
|
-
"Content-Type": "application/x-www-form-urlencoded"
|
|
163
|
-
},
|
|
164
|
-
body: new URLSearchParams({
|
|
165
|
-
grant_type: "authorization_code",
|
|
166
|
-
code: e,
|
|
167
|
-
redirect_uri: i,
|
|
168
|
-
client_id: this.authClientId,
|
|
169
|
-
code_verifier: r
|
|
170
|
-
})
|
|
171
|
-
});
|
|
172
|
-
if (!o.ok) {
|
|
173
|
-
const h = await o.text();
|
|
174
|
-
throw new Error(`Token exchange failed: ${o.status} ${h}`);
|
|
175
|
-
}
|
|
176
|
-
const s = await o.json(), n = Date.now() + (s.expires_in || 3600) * 1e3;
|
|
177
|
-
await chrome.storage.session.set({
|
|
178
|
-
[this.storageKeys.ACCESS_TOKEN]: s.access_token,
|
|
179
|
-
[this.storageKeys.REFRESH_TOKEN]: s.refresh_token,
|
|
180
|
-
[this.storageKeys.EXPIRES_AT]: n
|
|
181
|
-
}), await chrome.storage.session.remove([this.storageKeys.CODE_VERIFIER, this.storageKeys.STATE]);
|
|
182
|
-
}
|
|
183
|
-
// ============================================================================
|
|
184
|
-
// Storage Implementation (chrome.storage.session)
|
|
185
|
-
// ============================================================================
|
|
186
|
-
async _storageGet(e) {
|
|
187
|
-
const r = (await chrome.storage.session.get(e))[e];
|
|
188
|
-
return r !== void 0 ? String(r) : null;
|
|
189
|
-
}
|
|
190
|
-
async _storageSet(e) {
|
|
191
|
-
await chrome.storage.session.set(e);
|
|
192
|
-
}
|
|
193
|
-
async _storageRemove(e) {
|
|
194
|
-
await chrome.storage.session.remove(e);
|
|
195
|
-
}
|
|
196
126
|
_getRedirectUri() {
|
|
197
127
|
return chrome.identity.getRedirectURL("callback");
|
|
198
128
|
}
|
|
199
129
|
}
|
|
200
|
-
class
|
|
130
|
+
class _e {
|
|
201
131
|
constructor(e = {}, t) {
|
|
202
132
|
this.state = {
|
|
203
133
|
type: "extension",
|
|
204
134
|
extension: "not-initialized",
|
|
205
135
|
extensionId: null,
|
|
206
136
|
server: f
|
|
207
|
-
}, this.extensionId = null, this.broadcastListenerActive = !1, this.config = e, this.logger = new
|
|
137
|
+
}, this.extensionId = null, this.broadcastListenerActive = !1, this.config = e, this.logger = new x("ExtClient", e?.logLevel || "warn"), this.onStateChange = t ?? V, this.apiTimeoutMs = e.apiTimeoutMs ?? de, this.authClientId = e.authClientId ?? "";
|
|
208
138
|
}
|
|
209
139
|
/**
|
|
210
140
|
* Set client state and notify callback
|
|
@@ -272,17 +202,17 @@ class de {
|
|
|
272
202
|
async init(e = {}) {
|
|
273
203
|
if (!e.testConnection && !e.selectedConnection) {
|
|
274
204
|
this.logger.info("No testConnection or selectedConnection, returning not-initialized state");
|
|
275
|
-
const
|
|
276
|
-
return this.setState(
|
|
205
|
+
const n = z();
|
|
206
|
+
return this.setState(n), n;
|
|
277
207
|
}
|
|
278
208
|
if (this.extensionId && !e.testConnection)
|
|
279
209
|
return this.logger.debug("Already initialized with extensionId, skipping discovery"), this.state;
|
|
280
|
-
const t = e.timeoutMs ?? this.config.initParams?.extension?.timeoutMs ??
|
|
210
|
+
const t = e.timeoutMs ?? this.config.initParams?.extension?.timeoutMs ?? ce, r = e.savedState?.extensionId;
|
|
281
211
|
try {
|
|
282
212
|
if (!this.extensionId) {
|
|
283
213
|
if (r)
|
|
284
214
|
this.logger.info("Restoring with known extensionId:", r), await this.sendExtMessageWithTimeout(
|
|
285
|
-
|
|
215
|
+
p.SET_EXTENSION_ID,
|
|
286
216
|
{ extensionId: r },
|
|
287
217
|
t
|
|
288
218
|
), this.extensionId = r;
|
|
@@ -292,16 +222,16 @@ class de {
|
|
|
292
222
|
attempts: this.config.initParams?.extension?.attempts,
|
|
293
223
|
attemptWaitMs: this.config.initParams?.extension?.attemptWaitMs,
|
|
294
224
|
attemptTimeout: this.config.initParams?.extension?.attemptTimeout
|
|
295
|
-
},
|
|
296
|
-
|
|
225
|
+
}, i = await this.sendExtMessageWithTimeout(
|
|
226
|
+
p.DISCOVER_EXTENSION,
|
|
297
227
|
s,
|
|
298
228
|
t
|
|
299
229
|
);
|
|
300
|
-
this.extensionId =
|
|
230
|
+
this.extensionId = i.extensionId, this.logger.info("Extension discovered:", this.extensionId);
|
|
301
231
|
}
|
|
302
232
|
this.setupBroadcastListener();
|
|
303
233
|
}
|
|
304
|
-
const
|
|
234
|
+
const n = {
|
|
305
235
|
type: "extension",
|
|
306
236
|
extension: "ready",
|
|
307
237
|
extensionId: this.extensionId,
|
|
@@ -312,12 +242,12 @@ class de {
|
|
|
312
242
|
try {
|
|
313
243
|
o = await this.getServerState(), this.logger.info("Server connectivity tested, state:", o.status);
|
|
314
244
|
} catch (s) {
|
|
315
|
-
this.logger.error("Failed to get server state:", s), o =
|
|
245
|
+
this.logger.error("Failed to get server state:", s), o = K;
|
|
316
246
|
}
|
|
317
|
-
return this.setState({ ...
|
|
318
|
-
} catch (
|
|
319
|
-
this.logger.error("Failed to initialize extension:",
|
|
320
|
-
const o =
|
|
247
|
+
return this.setState({ ...n, server: o }), this.state;
|
|
248
|
+
} catch (n) {
|
|
249
|
+
this.logger.error("Failed to initialize extension:", n), this.extensionId = null;
|
|
250
|
+
const o = F();
|
|
321
251
|
return this.setState(o), this.state;
|
|
322
252
|
}
|
|
323
253
|
}
|
|
@@ -325,10 +255,10 @@ class de {
|
|
|
325
255
|
* Helper method to send ext message with timeout support
|
|
326
256
|
*/
|
|
327
257
|
async sendExtMessageWithTimeout(e, t, r = 1e4) {
|
|
328
|
-
const
|
|
258
|
+
const n = new Promise(
|
|
329
259
|
(o, s) => setTimeout(() => s(new Error("Timeout")), r)
|
|
330
260
|
);
|
|
331
|
-
return Promise.race([this.sendExtRequest(e, t),
|
|
261
|
+
return Promise.race([this.sendExtRequest(e, t), n]);
|
|
332
262
|
}
|
|
333
263
|
/**
|
|
334
264
|
* Send an EXT2EXT_CLIENT_REQUEST message and await EXT2EXT_CLIENT_RESPONSE
|
|
@@ -336,7 +266,7 @@ class de {
|
|
|
336
266
|
*/
|
|
337
267
|
async sendExtRequest(e, t) {
|
|
338
268
|
try {
|
|
339
|
-
const r = this.generateRequestId(),
|
|
269
|
+
const r = this.generateRequestId(), n = await chrome.runtime.sendMessage({
|
|
340
270
|
type: c.EXT2EXT_CLIENT_REQUEST,
|
|
341
271
|
requestId: r,
|
|
342
272
|
request: {
|
|
@@ -344,15 +274,15 @@ class de {
|
|
|
344
274
|
params: t
|
|
345
275
|
}
|
|
346
276
|
});
|
|
347
|
-
if (!
|
|
277
|
+
if (!n)
|
|
348
278
|
throw l("extension_error", "No response from background script");
|
|
349
|
-
if (
|
|
279
|
+
if (n.type !== c.EXT2EXT_CLIENT_RESPONSE)
|
|
350
280
|
throw l(
|
|
351
281
|
"extension_error",
|
|
352
282
|
"Invalid response type from background script"
|
|
353
283
|
);
|
|
354
|
-
const o =
|
|
355
|
-
if (
|
|
284
|
+
const o = n.response;
|
|
285
|
+
if (I(o)) {
|
|
356
286
|
const s = o.error.type || "extension_error";
|
|
357
287
|
throw l(s, o.error.message);
|
|
358
288
|
}
|
|
@@ -368,7 +298,7 @@ class de {
|
|
|
368
298
|
* Send an API_REQUEST message and await API_RESPONSE (internal)
|
|
369
299
|
* Returns ext2ext-specific ExtClientApiResponseMessage
|
|
370
300
|
*/
|
|
371
|
-
async sendRawApiMessage(e, t, r,
|
|
301
|
+
async sendRawApiMessage(e, t, r, n, o) {
|
|
372
302
|
const s = this.generateRequestId();
|
|
373
303
|
return await chrome.runtime.sendMessage({
|
|
374
304
|
type: c.EXT2EXT_CLIENT_API_REQUEST,
|
|
@@ -377,7 +307,7 @@ class de {
|
|
|
377
307
|
method: e,
|
|
378
308
|
endpoint: t,
|
|
379
309
|
body: r,
|
|
380
|
-
headers:
|
|
310
|
+
headers: n,
|
|
381
311
|
authenticated: o
|
|
382
312
|
}
|
|
383
313
|
});
|
|
@@ -386,7 +316,7 @@ class de {
|
|
|
386
316
|
* Send an API message and return ApiResponse
|
|
387
317
|
* @throws BodhiError on operational errors (network, timeout, extension-level)
|
|
388
318
|
*/
|
|
389
|
-
async sendApiRequest(e, t, r,
|
|
319
|
+
async sendApiRequest(e, t, r, n, o) {
|
|
390
320
|
try {
|
|
391
321
|
const s = new Promise(
|
|
392
322
|
(h, a) => setTimeout(
|
|
@@ -397,20 +327,20 @@ class de {
|
|
|
397
327
|
),
|
|
398
328
|
this.apiTimeoutMs
|
|
399
329
|
)
|
|
400
|
-
),
|
|
401
|
-
this.sendRawApiMessage(e, t, r,
|
|
330
|
+
), i = await Promise.race([
|
|
331
|
+
this.sendRawApiMessage(e, t, r, n, o),
|
|
402
332
|
s
|
|
403
333
|
]);
|
|
404
|
-
if (
|
|
405
|
-
const h =
|
|
406
|
-
throw new T(h,
|
|
334
|
+
if (le(i)) {
|
|
335
|
+
const h = i.error.type || "extension_error";
|
|
336
|
+
throw new T(h, i.error.message);
|
|
407
337
|
}
|
|
408
|
-
return
|
|
338
|
+
return i.response;
|
|
409
339
|
} catch (s) {
|
|
410
340
|
if (s instanceof T)
|
|
411
341
|
throw s;
|
|
412
|
-
const
|
|
413
|
-
throw new T("network_error",
|
|
342
|
+
const i = s instanceof Error ? s.message : String(s);
|
|
343
|
+
throw new T("network_error", i);
|
|
414
344
|
}
|
|
415
345
|
}
|
|
416
346
|
/**
|
|
@@ -421,12 +351,12 @@ class de {
|
|
|
421
351
|
*/
|
|
422
352
|
async login(e) {
|
|
423
353
|
return new Promise((t, r) => {
|
|
424
|
-
const
|
|
354
|
+
const n = async (o) => {
|
|
425
355
|
if (o && typeof o == "object" && "type" in o && o.type === "EXT2EXT_CLIENT_BROADCAST" && "event" in o && o.event === "authStateChanged") {
|
|
426
|
-
chrome.runtime.onMessage.removeListener(
|
|
356
|
+
chrome.runtime.onMessage.removeListener(n);
|
|
427
357
|
try {
|
|
428
358
|
const s = await this.getAuthState();
|
|
429
|
-
if (
|
|
359
|
+
if (Z(s)) {
|
|
430
360
|
r(
|
|
431
361
|
l("auth_error", `Login failed: ${s.error?.message}`)
|
|
432
362
|
);
|
|
@@ -442,8 +372,8 @@ class de {
|
|
|
442
372
|
}
|
|
443
373
|
}
|
|
444
374
|
};
|
|
445
|
-
chrome.runtime.onMessage.addListener(
|
|
446
|
-
chrome.runtime.onMessage.removeListener(
|
|
375
|
+
chrome.runtime.onMessage.addListener(n), this.sendExtRequest(p.LOGIN, e).catch((o) => {
|
|
376
|
+
chrome.runtime.onMessage.removeListener(n), r(o);
|
|
447
377
|
});
|
|
448
378
|
});
|
|
449
379
|
}
|
|
@@ -453,12 +383,15 @@ class de {
|
|
|
453
383
|
* @returns AuthLoggedOut with logged out state
|
|
454
384
|
*/
|
|
455
385
|
async logout() {
|
|
456
|
-
await this.sendExtRequest(
|
|
386
|
+
await this.sendExtRequest(p.LOGOUT);
|
|
457
387
|
const e = {
|
|
458
388
|
status: "unauthenticated",
|
|
459
389
|
user: null,
|
|
460
390
|
accessToken: null,
|
|
461
|
-
error: null
|
|
391
|
+
error: null,
|
|
392
|
+
refreshToken: null,
|
|
393
|
+
expiresAt: null,
|
|
394
|
+
isTokenRefresh: !1
|
|
462
395
|
};
|
|
463
396
|
return this.setAuthState(e), e;
|
|
464
397
|
}
|
|
@@ -469,8 +402,8 @@ class de {
|
|
|
469
402
|
*/
|
|
470
403
|
async getAuthState() {
|
|
471
404
|
return this.isClientInitialized() ? (await this.sendExtRequest(
|
|
472
|
-
|
|
473
|
-
)).authState :
|
|
405
|
+
p.GET_AUTH_STATE
|
|
406
|
+
)).authState : G;
|
|
474
407
|
}
|
|
475
408
|
/**
|
|
476
409
|
* Ping bodhi-browser-ext API via /ping endpoint
|
|
@@ -487,11 +420,11 @@ class de {
|
|
|
487
420
|
try {
|
|
488
421
|
e = await this.sendApiRequest("GET", "/bodhi/v1/info");
|
|
489
422
|
} catch (o) {
|
|
490
|
-
const s = o instanceof Error ? o.message : "Connection failed",
|
|
423
|
+
const s = o instanceof Error ? o.message : "Connection failed", i = o instanceof T ? o.code : "extension_error";
|
|
491
424
|
return {
|
|
492
425
|
status: "not-reachable",
|
|
493
426
|
version: null,
|
|
494
|
-
error: { message: s, type:
|
|
427
|
+
error: { message: s, type: i }
|
|
495
428
|
};
|
|
496
429
|
}
|
|
497
430
|
if (e.status >= 400)
|
|
@@ -500,30 +433,30 @@ class de {
|
|
|
500
433
|
version: null,
|
|
501
434
|
error: { message: "API error from server", type: "extension_error" }
|
|
502
435
|
};
|
|
503
|
-
const t = e.body, r = t.version || "unknown",
|
|
436
|
+
const t = e.body, r = t.version || "unknown", n = { deployment: t.deployment ?? null, client_id: t.client_id ?? null };
|
|
504
437
|
switch (t.status) {
|
|
505
438
|
case "ready":
|
|
506
|
-
return { status: "ready", version: r, error: null, ...
|
|
439
|
+
return { status: "ready", version: r, error: null, ...n };
|
|
507
440
|
case "setup":
|
|
508
441
|
return {
|
|
509
442
|
status: "setup",
|
|
510
443
|
version: r,
|
|
511
444
|
error: t.error ? { message: t.error.message, type: t.error.type } : { message: "Setup required", type: "extension_error" },
|
|
512
|
-
...
|
|
445
|
+
...n
|
|
513
446
|
};
|
|
514
447
|
case "resource_admin":
|
|
515
448
|
return {
|
|
516
449
|
status: "resource_admin",
|
|
517
450
|
version: r,
|
|
518
451
|
error: t.error ? { message: t.error.message, type: t.error.type } : { message: "Resource admin required", type: "extension_error" },
|
|
519
|
-
...
|
|
452
|
+
...n
|
|
520
453
|
};
|
|
521
454
|
case "error":
|
|
522
455
|
return {
|
|
523
456
|
status: "error",
|
|
524
457
|
version: r,
|
|
525
458
|
error: t.error ? { message: t.error.message, type: t.error.type } : { message: "Server error", type: "extension_error" },
|
|
526
|
-
...
|
|
459
|
+
...n
|
|
527
460
|
};
|
|
528
461
|
default:
|
|
529
462
|
return {
|
|
@@ -539,69 +472,69 @@ class de {
|
|
|
539
472
|
/**
|
|
540
473
|
* Generic streaming method
|
|
541
474
|
*/
|
|
542
|
-
async *stream(e, t, r,
|
|
475
|
+
async *stream(e, t, r, n, o = !0) {
|
|
543
476
|
const s = this.generateRequestId();
|
|
544
477
|
this.logger.debug("Starting stream", {
|
|
545
478
|
method: e,
|
|
546
479
|
endpoint: t,
|
|
547
480
|
requestId: s
|
|
548
481
|
});
|
|
549
|
-
const
|
|
550
|
-
start: (
|
|
551
|
-
|
|
482
|
+
const i = chrome.runtime.connect({ name: M }), a = new ReadableStream({
|
|
483
|
+
start: (E) => {
|
|
484
|
+
i.onMessage.addListener((d) => {
|
|
552
485
|
if (d.requestId === s)
|
|
553
486
|
switch (d.type) {
|
|
554
487
|
case c.EXT2EXT_CLIENT_STREAM_DONE:
|
|
555
|
-
this.logger.debug("Stream complete", { requestId: s }),
|
|
488
|
+
this.logger.debug("Stream complete", { requestId: s }), E.close(), i.disconnect();
|
|
556
489
|
break;
|
|
557
490
|
case c.EXT2EXT_CLIENT_STREAM_ERROR:
|
|
558
491
|
this.logger.error("Stream error", {
|
|
559
492
|
requestId: s,
|
|
560
493
|
error: JSON.stringify(d.error)
|
|
561
|
-
}),
|
|
494
|
+
}), E.error(
|
|
562
495
|
new T(
|
|
563
496
|
"extension_error",
|
|
564
497
|
d.error.message
|
|
565
498
|
)
|
|
566
|
-
),
|
|
499
|
+
), i.disconnect();
|
|
567
500
|
break;
|
|
568
501
|
case c.EXT2EXT_CLIENT_STREAM_API_ERROR: {
|
|
569
|
-
const
|
|
502
|
+
const u = d;
|
|
570
503
|
this.logger.error("Stream API error", {
|
|
571
504
|
requestId: s,
|
|
572
|
-
error:
|
|
573
|
-
}),
|
|
574
|
-
new
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
505
|
+
error: u.response.body?.error
|
|
506
|
+
}), E.error(
|
|
507
|
+
new Q(
|
|
508
|
+
u.response.status,
|
|
509
|
+
u.response.body,
|
|
510
|
+
u.response.body?.error?.message || "API error"
|
|
578
511
|
)
|
|
579
|
-
),
|
|
512
|
+
), i.disconnect();
|
|
580
513
|
break;
|
|
581
514
|
}
|
|
582
515
|
case c.EXT2EXT_CLIENT_STREAM_CHUNK: {
|
|
583
|
-
const
|
|
584
|
-
|
|
516
|
+
const u = d;
|
|
517
|
+
te(u.response) && E.enqueue(u.response.body);
|
|
585
518
|
break;
|
|
586
519
|
}
|
|
587
520
|
}
|
|
588
|
-
}),
|
|
521
|
+
}), i.onDisconnect.addListener(() => {
|
|
589
522
|
this.logger.debug("Port disconnected", { requestId: s });
|
|
590
523
|
try {
|
|
591
|
-
|
|
524
|
+
E.error(new T("connection_closed", "Connection closed unexpectedly"));
|
|
592
525
|
} catch {
|
|
593
526
|
}
|
|
594
|
-
}),
|
|
527
|
+
}), i.postMessage({
|
|
595
528
|
type: c.EXT2EXT_CLIENT_STREAM_REQUEST,
|
|
596
529
|
requestId: s,
|
|
597
|
-
request: { method: e, endpoint: t, body: r, headers:
|
|
530
|
+
request: { method: e, endpoint: t, body: r, headers: n, authenticated: o }
|
|
598
531
|
});
|
|
599
532
|
}
|
|
600
533
|
}).getReader();
|
|
601
534
|
try {
|
|
602
535
|
for (; ; ) {
|
|
603
|
-
const { done:
|
|
604
|
-
if (
|
|
536
|
+
const { done: E, value: d } = await a.read();
|
|
537
|
+
if (E) {
|
|
605
538
|
this.logger.debug("Stream iteration complete");
|
|
606
539
|
break;
|
|
607
540
|
}
|
|
@@ -611,20 +544,86 @@ class de {
|
|
|
611
544
|
a.releaseLock();
|
|
612
545
|
}
|
|
613
546
|
}
|
|
547
|
+
/**
|
|
548
|
+
* Raw text streaming method - no SSE/JSON parsing
|
|
549
|
+
* Returns status, headers, and async generator of raw text chunks
|
|
550
|
+
*/
|
|
551
|
+
async streamText(e, t, r, n, o = !0) {
|
|
552
|
+
const s = this.generateRequestId();
|
|
553
|
+
return new Promise((i, h) => {
|
|
554
|
+
let a, E = !1;
|
|
555
|
+
const d = new ReadableStream({
|
|
556
|
+
start: (g) => {
|
|
557
|
+
a = g;
|
|
558
|
+
}
|
|
559
|
+
}), u = chrome.runtime.connect({ name: O });
|
|
560
|
+
u.onMessage.addListener((g) => {
|
|
561
|
+
if (g.requestId === s)
|
|
562
|
+
switch (g.type) {
|
|
563
|
+
case c.EXT2EXT_CLIENT_STREAM_TEXT_START: {
|
|
564
|
+
E = !0;
|
|
565
|
+
async function* m(U) {
|
|
566
|
+
const C = U.getReader();
|
|
567
|
+
try {
|
|
568
|
+
for (; ; ) {
|
|
569
|
+
const { done: q, value: D } = await C.read();
|
|
570
|
+
if (q) break;
|
|
571
|
+
yield D;
|
|
572
|
+
}
|
|
573
|
+
} finally {
|
|
574
|
+
C.releaseLock();
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
i({
|
|
578
|
+
status: g.status,
|
|
579
|
+
headers: g.headers,
|
|
580
|
+
body: m(d)
|
|
581
|
+
});
|
|
582
|
+
break;
|
|
583
|
+
}
|
|
584
|
+
case c.EXT2EXT_CLIENT_STREAM_TEXT_CHUNK:
|
|
585
|
+
a.enqueue(g.chunk);
|
|
586
|
+
break;
|
|
587
|
+
case c.EXT2EXT_CLIENT_STREAM_TEXT_DONE:
|
|
588
|
+
a.close(), u.disconnect();
|
|
589
|
+
break;
|
|
590
|
+
case c.EXT2EXT_CLIENT_STREAM_TEXT_ERROR: {
|
|
591
|
+
const m = l("extension_error", g.error.message);
|
|
592
|
+
E ? a.error(m) : h(m), u.disconnect();
|
|
593
|
+
break;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
}), u.onDisconnect.addListener(() => {
|
|
597
|
+
if (!E)
|
|
598
|
+
h(l("extension_error", "Connection closed unexpectedly"));
|
|
599
|
+
else
|
|
600
|
+
try {
|
|
601
|
+
a.error(
|
|
602
|
+
l("extension_error", "Connection closed unexpectedly")
|
|
603
|
+
);
|
|
604
|
+
} catch {
|
|
605
|
+
}
|
|
606
|
+
}), u.postMessage({
|
|
607
|
+
type: c.EXT2EXT_CLIENT_STREAM_TEXT_REQUEST,
|
|
608
|
+
requestId: s,
|
|
609
|
+
request: { method: e, endpoint: t, body: r, headers: n, authenticated: o }
|
|
610
|
+
});
|
|
611
|
+
});
|
|
612
|
+
}
|
|
614
613
|
// ============================================================================
|
|
615
614
|
// OpenAI-Compatible Namespaced API
|
|
616
615
|
// ============================================================================
|
|
617
616
|
get chat() {
|
|
618
|
-
return this._chat ??= new
|
|
617
|
+
return this._chat ??= new H(this);
|
|
619
618
|
}
|
|
620
619
|
get models() {
|
|
621
|
-
return this._models ??= new
|
|
620
|
+
return this._models ??= new W(this);
|
|
622
621
|
}
|
|
623
622
|
get embeddings() {
|
|
624
|
-
return this._embeddings ??= new
|
|
623
|
+
return this._embeddings ??= new J(this);
|
|
625
624
|
}
|
|
626
625
|
get mcps() {
|
|
627
|
-
return this._mcps ??= new
|
|
626
|
+
return this._mcps ??= new Y(this);
|
|
628
627
|
}
|
|
629
628
|
// ============================================================================
|
|
630
629
|
// Access Request Methods
|
|
@@ -648,7 +647,7 @@ class de {
|
|
|
648
647
|
);
|
|
649
648
|
}
|
|
650
649
|
async pollAccessRequestStatus(e, t) {
|
|
651
|
-
return
|
|
650
|
+
return k(
|
|
652
651
|
(r) => this.getAccessRequestStatus(r),
|
|
653
652
|
e,
|
|
654
653
|
t
|
|
@@ -671,25 +670,27 @@ class de {
|
|
|
671
670
|
};
|
|
672
671
|
}
|
|
673
672
|
}
|
|
674
|
-
class
|
|
673
|
+
class fe extends j {
|
|
675
674
|
constructor(e, t, r) {
|
|
676
|
-
const
|
|
677
|
-
basePath:
|
|
678
|
-
authServerUrl:
|
|
679
|
-
logLevel:
|
|
680
|
-
apiTimeoutMs:
|
|
681
|
-
|
|
675
|
+
const n = t || {}, o = {
|
|
676
|
+
basePath: n.basePath || "/",
|
|
677
|
+
authServerUrl: n.authServerUrl || "https://id.getbodhi.app/realms/bodhi",
|
|
678
|
+
logLevel: n.logLevel || "warn",
|
|
679
|
+
apiTimeoutMs: n.apiTimeoutMs,
|
|
680
|
+
storage: n.storage,
|
|
681
|
+
initialTokens: n.initialTokens,
|
|
682
|
+
initParams: n.initParams
|
|
682
683
|
};
|
|
683
684
|
super(e, o, r);
|
|
684
685
|
}
|
|
685
686
|
createLogger(e) {
|
|
686
|
-
return new
|
|
687
|
+
return new x("ExtUIClient", e.logLevel);
|
|
687
688
|
}
|
|
688
689
|
createStoragePrefix(e) {
|
|
689
|
-
return
|
|
690
|
+
return X(e.basePath, N.EXT);
|
|
690
691
|
}
|
|
691
692
|
createExtClient(e, t) {
|
|
692
|
-
return new
|
|
693
|
+
return new _e(
|
|
693
694
|
{
|
|
694
695
|
authClientId: this.authClientId,
|
|
695
696
|
logLevel: e.logLevel,
|
|
@@ -700,24 +701,26 @@ class me extends J {
|
|
|
700
701
|
);
|
|
701
702
|
}
|
|
702
703
|
createDirectClient(e, t, r) {
|
|
703
|
-
return new
|
|
704
|
+
return new ge(
|
|
704
705
|
{
|
|
705
706
|
authClientId: e,
|
|
706
707
|
authServerUrl: t.authServerUrl,
|
|
707
708
|
logLevel: t.logLevel,
|
|
708
709
|
basePath: t.basePath,
|
|
709
|
-
apiTimeoutMs: t.apiTimeoutMs
|
|
710
|
+
apiTimeoutMs: t.apiTimeoutMs,
|
|
711
|
+
storage: t.storage,
|
|
712
|
+
initialTokens: t.initialTokens
|
|
710
713
|
},
|
|
711
714
|
r
|
|
712
715
|
);
|
|
713
716
|
}
|
|
714
717
|
}
|
|
715
|
-
const
|
|
718
|
+
const pe = ["ggedphdcbekjlomjaidbajglgihbeaon"], me = ["bjdjhiombmfbcoeojijpfckljjghmjbf"], y = "production", S = class S {
|
|
716
719
|
// ============================================================================
|
|
717
720
|
// Constructor
|
|
718
721
|
// ============================================================================
|
|
719
722
|
constructor(e, t) {
|
|
720
|
-
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
|
|
723
|
+
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 x("BodhiExtClient", t?.logLevel || "warn"), this.attempts = t?.attempts ?? he, this.attemptWaitMs = t?.attemptWaitMs ?? Ee, this.attemptTimeout = t?.attemptTimeout ?? ue, this.authEndpoints = {
|
|
721
724
|
authorize: `${this.authServerUrl}/protocol/openid-connect/auth`,
|
|
722
725
|
token: `${this.authServerUrl}/protocol/openid-connect/token`,
|
|
723
726
|
userinfo: `${this.authServerUrl}/protocol/openid-connect/userinfo`,
|
|
@@ -735,11 +738,11 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
735
738
|
}
|
|
736
739
|
static generateCodeVerifier() {
|
|
737
740
|
const e = new Uint8Array(32);
|
|
738
|
-
return crypto.getRandomValues(e),
|
|
741
|
+
return crypto.getRandomValues(e), S.base64UrlEncode(e.buffer);
|
|
739
742
|
}
|
|
740
743
|
static async generateCodeChallenge(e) {
|
|
741
|
-
const r = new TextEncoder().encode(e),
|
|
742
|
-
return
|
|
744
|
+
const r = new TextEncoder().encode(e), n = await crypto.subtle.digest("SHA-256", r);
|
|
745
|
+
return S.base64UrlEncode(n);
|
|
743
746
|
}
|
|
744
747
|
// ============================================================================
|
|
745
748
|
// State Management
|
|
@@ -758,7 +761,7 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
758
761
|
* Get extension IDs for current environment
|
|
759
762
|
*/
|
|
760
763
|
getExtensionIdsForEnvironment() {
|
|
761
|
-
const t =
|
|
764
|
+
const t = y !== "production" ? pe : me;
|
|
762
765
|
return this.logger.info("[Ext2Ext/Registry] Environment: production"), this.logger.debug("[Ext2Ext/Registry] Using extension IDs:", t), t;
|
|
763
766
|
}
|
|
764
767
|
/**
|
|
@@ -768,7 +771,7 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
768
771
|
return this.logger.debug(
|
|
769
772
|
`[Ext2Ext/Discovery] Pinging extension: ${e} with timeout ${this.attemptTimeout}ms`
|
|
770
773
|
), new Promise((t, r) => {
|
|
771
|
-
const
|
|
774
|
+
const n = setTimeout(() => {
|
|
772
775
|
this.logger.debug(`[Ext2Ext/Discovery] Timeout waiting for extension ${e}`), r(new Error("Timeout"));
|
|
773
776
|
}, this.attemptTimeout);
|
|
774
777
|
try {
|
|
@@ -780,7 +783,7 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
780
783
|
}
|
|
781
784
|
};
|
|
782
785
|
this.logger.debug(`[Ext2Ext/Discovery] Sending message to ${e}:`, o), chrome.runtime.sendMessage(e, o, (s) => {
|
|
783
|
-
if (clearTimeout(
|
|
786
|
+
if (clearTimeout(n), chrome.runtime.lastError) {
|
|
784
787
|
this.logger.error(
|
|
785
788
|
`[Ext2Ext/Discovery] Error from extension ${e}:`,
|
|
786
789
|
chrome.runtime.lastError.message
|
|
@@ -788,14 +791,14 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
788
791
|
return;
|
|
789
792
|
}
|
|
790
793
|
this.logger.debug(`[Ext2Ext/Discovery] Response from ${e}:`, s);
|
|
791
|
-
const
|
|
792
|
-
|
|
794
|
+
const i = s;
|
|
795
|
+
i && i.type === _.EXT_RESPONSE ? (this.logger.debug(`[Ext2Ext/Discovery] ✓ Extension ${e} responded`), t(!0)) : (this.logger.error(
|
|
793
796
|
`[Ext2Ext/Discovery] Invalid response from ${e}:`,
|
|
794
797
|
s
|
|
795
798
|
), r(new Error("Invalid response")));
|
|
796
799
|
});
|
|
797
800
|
} catch (o) {
|
|
798
|
-
this.logger.error(`[Ext2Ext/Discovery] Exception pinging ${e}:`, o), clearTimeout(
|
|
801
|
+
this.logger.error(`[Ext2Ext/Discovery] Exception pinging ${e}:`, o), clearTimeout(n), r(o);
|
|
799
802
|
}
|
|
800
803
|
});
|
|
801
804
|
}
|
|
@@ -810,9 +813,9 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
810
813
|
* @param params Resolved discovery params
|
|
811
814
|
*/
|
|
812
815
|
async discoverBodhiExtension(e) {
|
|
813
|
-
const { attempts: t, attemptWaitMs: r, attemptTimeout:
|
|
816
|
+
const { attempts: t, attemptWaitMs: r, attemptTimeout: n } = e;
|
|
814
817
|
this.logger.info(
|
|
815
|
-
`[Ext2Ext/Discovery] Starting discovery: ${t} attempts per ID, ${
|
|
818
|
+
`[Ext2Ext/Discovery] Starting discovery: ${t} attempts per ID, ${n}ms timeout, ${r}ms between attempts`
|
|
816
819
|
);
|
|
817
820
|
const o = this.getExtensionIdsForEnvironment();
|
|
818
821
|
this.logger.debug(
|
|
@@ -829,9 +832,9 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
829
832
|
success: !0,
|
|
830
833
|
extensionId: h
|
|
831
834
|
};
|
|
832
|
-
} catch (
|
|
835
|
+
} catch (E) {
|
|
833
836
|
this.logger.debug(
|
|
834
|
-
`[Ext2Ext/Discovery] Attempt ${a} failed for ${h}: ${
|
|
837
|
+
`[Ext2Ext/Discovery] Attempt ${a} failed for ${h}: ${E instanceof Error ? E.message : "Unknown error"}`
|
|
835
838
|
), a < t && await this.sleep(r);
|
|
836
839
|
}
|
|
837
840
|
}
|
|
@@ -839,10 +842,10 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
839
842
|
`[Ext2Ext/Discovery] ✗ Not found: ${h} after ${t} attempts`
|
|
840
843
|
);
|
|
841
844
|
}
|
|
842
|
-
const s = o.join(", "),
|
|
843
|
-
return this.logger.error(`[Ext2Ext/Discovery] ${
|
|
845
|
+
const s = o.join(", "), i = `Extension not found. Tried ${o.length} IDs with ${t} attempts each: ${s}`;
|
|
846
|
+
return this.logger.error(`[Ext2Ext/Discovery] ${i}`), {
|
|
844
847
|
success: !1,
|
|
845
|
-
error:
|
|
848
|
+
error: i
|
|
846
849
|
};
|
|
847
850
|
}
|
|
848
851
|
// ============================================================================
|
|
@@ -856,7 +859,7 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
856
859
|
this.logger.debug("[BodhiExtClient] Listeners already initialized, skipping");
|
|
857
860
|
return;
|
|
858
861
|
}
|
|
859
|
-
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 ===
|
|
862
|
+
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 === p.DISCOVER_EXTENSION) ? (e.type === c.EXT2EXT_CLIENT_REQUEST ? r({
|
|
860
863
|
type: c.EXT2EXT_CLIENT_RESPONSE,
|
|
861
864
|
requestId: e.requestId,
|
|
862
865
|
response: {
|
|
@@ -873,30 +876,19 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
873
876
|
type: "NOT_INITIALIZED"
|
|
874
877
|
}
|
|
875
878
|
}), !0) : (this.logger.debug(`[BodhiExtClient] Processing message.type=${e.type}`), (async () => {
|
|
876
|
-
const
|
|
877
|
-
r(
|
|
878
|
-
})(), !0)),
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
message: "Unknown stream message type",
|
|
890
|
-
type: "extension_error"
|
|
891
|
-
}
|
|
892
|
-
});
|
|
893
|
-
return;
|
|
894
|
-
}
|
|
895
|
-
await this.handleStreamRequest(e, t);
|
|
896
|
-
}), e.onDisconnect.addListener(() => {
|
|
897
|
-
this.logger.info("[BodhiExtClient] Streaming port disconnected");
|
|
898
|
-
});
|
|
899
|
-
}), this.logger.info("[BodhiExtClient] Streaming listeners initialized");
|
|
879
|
+
const n = await this.handleAction(e);
|
|
880
|
+
r(n);
|
|
881
|
+
})(), !0)), this.registerStreamPortListener(
|
|
882
|
+
M,
|
|
883
|
+
c.EXT2EXT_CLIENT_STREAM_REQUEST,
|
|
884
|
+
c.EXT2EXT_CLIENT_STREAM_ERROR,
|
|
885
|
+
(e, t) => this.handleStreamRequest(e, t)
|
|
886
|
+
), this.registerStreamPortListener(
|
|
887
|
+
O,
|
|
888
|
+
c.EXT2EXT_CLIENT_STREAM_TEXT_REQUEST,
|
|
889
|
+
c.EXT2EXT_CLIENT_STREAM_TEXT_ERROR,
|
|
890
|
+
(e, t) => this.handleStreamTextRequest(e, t)
|
|
891
|
+
), this.logger.info("[BodhiExtClient] Streaming listeners initialized");
|
|
900
892
|
}
|
|
901
893
|
/**
|
|
902
894
|
* Initialize client: setup listeners and discover bodhi-browser-ext
|
|
@@ -968,7 +960,7 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
968
960
|
Authorization: `Bearer ${o}`
|
|
969
961
|
}, this.logger.debug("[BodhiExtClient] Injected auth token for authenticated request");
|
|
970
962
|
}
|
|
971
|
-
const
|
|
963
|
+
const n = await this.sendApiRequest(
|
|
972
964
|
e.request.method,
|
|
973
965
|
e.request.endpoint,
|
|
974
966
|
e.request.body,
|
|
@@ -977,7 +969,7 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
977
969
|
return {
|
|
978
970
|
type: c.EXT2EXT_CLIENT_API_RESPONSE,
|
|
979
971
|
requestId: t,
|
|
980
|
-
response:
|
|
972
|
+
response: n
|
|
981
973
|
};
|
|
982
974
|
} catch (r) {
|
|
983
975
|
return this.logger.error("[BodhiExtClient] API request failed:", r), {
|
|
@@ -997,53 +989,53 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
997
989
|
* @returns Action response message (success or error)
|
|
998
990
|
*/
|
|
999
991
|
async handleExtClientRequest(e) {
|
|
1000
|
-
const { requestId: t, request: r } = e, { action:
|
|
1001
|
-
this.logger.debug(`[BodhiExtClient] Handling action: ${
|
|
992
|
+
const { requestId: t, request: r } = e, { action: n, params: o } = r;
|
|
993
|
+
this.logger.debug(`[BodhiExtClient] Handling action: ${n}`);
|
|
1002
994
|
try {
|
|
1003
995
|
let s = {};
|
|
1004
|
-
switch (
|
|
1005
|
-
case
|
|
1006
|
-
const
|
|
1007
|
-
await this.init(
|
|
996
|
+
switch (n) {
|
|
997
|
+
case p.DISCOVER_EXTENSION: {
|
|
998
|
+
const i = o;
|
|
999
|
+
await this.init(i), this.logger.info("[BodhiExtClient] Discovery successful:", {
|
|
1008
1000
|
extensionId: this.extensionId,
|
|
1009
|
-
environment:
|
|
1001
|
+
environment: y
|
|
1010
1002
|
}), s = {
|
|
1011
1003
|
extensionId: this.extensionId,
|
|
1012
|
-
environment:
|
|
1004
|
+
environment: y
|
|
1013
1005
|
};
|
|
1014
1006
|
break;
|
|
1015
1007
|
}
|
|
1016
|
-
case
|
|
1017
|
-
const { extensionId:
|
|
1018
|
-
this.extensionId =
|
|
1008
|
+
case p.SET_EXTENSION_ID: {
|
|
1009
|
+
const { extensionId: i } = o;
|
|
1010
|
+
this.extensionId = i, this.state = "ready", this.logger.info("[BodhiExtClient] Extension ID set:", { extensionId: i }), s = { success: !0 };
|
|
1019
1011
|
break;
|
|
1020
1012
|
}
|
|
1021
|
-
case
|
|
1022
|
-
const
|
|
1023
|
-
return
|
|
1013
|
+
case p.GET_EXTENSION_ID: {
|
|
1014
|
+
const i = await this.sendExtRequestRaw(re.GET_EXTENSION_ID, o);
|
|
1015
|
+
return I(i.response) ? {
|
|
1024
1016
|
type: c.EXT2EXT_CLIENT_RESPONSE,
|
|
1025
1017
|
requestId: t,
|
|
1026
1018
|
response: {
|
|
1027
1019
|
error: {
|
|
1028
|
-
message:
|
|
1029
|
-
type:
|
|
1020
|
+
message: i.response.error.message || `Extension request failed to get extension ID: ${JSON.stringify(i.response)}`,
|
|
1021
|
+
type: i.response.error.type
|
|
1030
1022
|
}
|
|
1031
1023
|
}
|
|
1032
1024
|
} : {
|
|
1033
1025
|
type: c.EXT2EXT_CLIENT_RESPONSE,
|
|
1034
1026
|
requestId: t,
|
|
1035
|
-
response:
|
|
1027
|
+
response: i.response
|
|
1036
1028
|
};
|
|
1037
1029
|
}
|
|
1038
|
-
case
|
|
1039
|
-
const
|
|
1040
|
-
await this.login(
|
|
1030
|
+
case p.LOGIN: {
|
|
1031
|
+
const i = o;
|
|
1032
|
+
await this.login(i), this.broadcastAuthStateChange();
|
|
1041
1033
|
break;
|
|
1042
1034
|
}
|
|
1043
|
-
case
|
|
1035
|
+
case p.LOGOUT:
|
|
1044
1036
|
await this.logout(), this.broadcastAuthStateChange();
|
|
1045
1037
|
break;
|
|
1046
|
-
case
|
|
1038
|
+
case p.GET_AUTH_STATE:
|
|
1047
1039
|
s = { authState: await this.getAuthState() };
|
|
1048
1040
|
break;
|
|
1049
1041
|
default:
|
|
@@ -1051,7 +1043,7 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1051
1043
|
type: c.EXT2EXT_CLIENT_RESPONSE,
|
|
1052
1044
|
requestId: t,
|
|
1053
1045
|
response: {
|
|
1054
|
-
error: { message: `Unknown action: ${
|
|
1046
|
+
error: { message: `Unknown action: ${n}`, type: "UNKNOWN_ACTION" }
|
|
1055
1047
|
}
|
|
1056
1048
|
};
|
|
1057
1049
|
}
|
|
@@ -1109,13 +1101,13 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1109
1101
|
if (!this.extensionId)
|
|
1110
1102
|
throw new Error("Extension not discovered. Please detect Bodhi extension before login.");
|
|
1111
1103
|
e?.flowType === "redirect" && this.logger.warn("Extension mode does not support redirect flow type; using popup instead");
|
|
1112
|
-
const r = e?.userRole ?? "scope_user_user",
|
|
1113
|
-
e?.requested &&
|
|
1114
|
-
const o =
|
|
1104
|
+
const r = e?.userRole ?? "scope_user_user", n = new v(this.authClientId).requestedRole(r).flowType("popup");
|
|
1105
|
+
e?.requested && n.requested(e.requested);
|
|
1106
|
+
const o = n.build(), s = await this.requestAccess(o), { id: i, review_url: h } = L(s);
|
|
1115
1107
|
await chrome.tabs.create({ url: h });
|
|
1116
|
-
const a = await this.pollAccessRequestStatus(
|
|
1117
|
-
intervalMs: e?.pollIntervalMs ??
|
|
1118
|
-
timeoutMs: e?.pollTimeoutMs ??
|
|
1108
|
+
const a = await this.pollAccessRequestStatus(i, {
|
|
1109
|
+
intervalMs: e?.pollIntervalMs ?? b,
|
|
1110
|
+
timeoutMs: e?.pollTimeoutMs ?? P
|
|
1119
1111
|
});
|
|
1120
1112
|
if (a.status !== "approved")
|
|
1121
1113
|
throw l("auth_error", `Access request ${a.status}`);
|
|
@@ -1133,7 +1125,7 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1133
1125
|
async exchangeCodeForTokens(e) {
|
|
1134
1126
|
if ((await this.getAuthState()).status === "authenticated")
|
|
1135
1127
|
return;
|
|
1136
|
-
const { codeVerifier: r } = await chrome.storage.session.get("codeVerifier"),
|
|
1128
|
+
const { codeVerifier: r } = await chrome.storage.session.get("codeVerifier"), n = chrome.identity.getRedirectURL("callback"), o = await fetch(this.authEndpoints.token, {
|
|
1137
1129
|
method: "POST",
|
|
1138
1130
|
headers: {
|
|
1139
1131
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
@@ -1141,14 +1133,14 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1141
1133
|
body: new URLSearchParams({
|
|
1142
1134
|
grant_type: "authorization_code",
|
|
1143
1135
|
code: e,
|
|
1144
|
-
redirect_uri:
|
|
1136
|
+
redirect_uri: n,
|
|
1145
1137
|
client_id: this.authClientId,
|
|
1146
1138
|
code_verifier: r
|
|
1147
1139
|
})
|
|
1148
1140
|
});
|
|
1149
1141
|
if (!o.ok) {
|
|
1150
|
-
const
|
|
1151
|
-
throw new Error(`Token exchange failed: ${o.status} ${
|
|
1142
|
+
const i = await o.text();
|
|
1143
|
+
throw new Error(`Token exchange failed: ${o.status} ${i}`);
|
|
1152
1144
|
}
|
|
1153
1145
|
const s = await o.json();
|
|
1154
1146
|
await this.storeTokens({
|
|
@@ -1165,7 +1157,15 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1165
1157
|
async getAuthState() {
|
|
1166
1158
|
const e = await this._getAccessTokenRaw();
|
|
1167
1159
|
if (!e)
|
|
1168
|
-
return {
|
|
1160
|
+
return {
|
|
1161
|
+
status: "unauthenticated",
|
|
1162
|
+
user: null,
|
|
1163
|
+
accessToken: null,
|
|
1164
|
+
error: null,
|
|
1165
|
+
refreshToken: null,
|
|
1166
|
+
expiresAt: null,
|
|
1167
|
+
isTokenRefresh: !1
|
|
1168
|
+
};
|
|
1169
1169
|
try {
|
|
1170
1170
|
const t = this.parseJwt(e);
|
|
1171
1171
|
return {
|
|
@@ -1179,10 +1179,21 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1179
1179
|
preferred_username: t.preferred_username
|
|
1180
1180
|
},
|
|
1181
1181
|
accessToken: e,
|
|
1182
|
-
error: null
|
|
1182
|
+
error: null,
|
|
1183
|
+
refreshToken: null,
|
|
1184
|
+
expiresAt: null,
|
|
1185
|
+
isTokenRefresh: !1
|
|
1183
1186
|
};
|
|
1184
1187
|
} catch (t) {
|
|
1185
|
-
return this.logger.error("Failed to parse token:", t), {
|
|
1188
|
+
return this.logger.error("Failed to parse token:", t), {
|
|
1189
|
+
status: "unauthenticated",
|
|
1190
|
+
user: null,
|
|
1191
|
+
accessToken: null,
|
|
1192
|
+
error: null,
|
|
1193
|
+
refreshToken: null,
|
|
1194
|
+
expiresAt: null,
|
|
1195
|
+
isTokenRefresh: !1
|
|
1196
|
+
};
|
|
1186
1197
|
}
|
|
1187
1198
|
}
|
|
1188
1199
|
/**
|
|
@@ -1226,21 +1237,21 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1226
1237
|
);
|
|
1227
1238
|
}
|
|
1228
1239
|
async pollAccessRequestStatus(e, t) {
|
|
1229
|
-
return
|
|
1240
|
+
return k(
|
|
1230
1241
|
(r) => this.getAccessRequestStatus(r),
|
|
1231
1242
|
e,
|
|
1232
1243
|
t
|
|
1233
1244
|
);
|
|
1234
1245
|
}
|
|
1235
1246
|
async performOAuthPkce(e) {
|
|
1236
|
-
const t =
|
|
1247
|
+
const t = S.generateCodeVerifier(), r = await S.generateCodeChallenge(t), n = S.generateCodeVerifier();
|
|
1237
1248
|
await chrome.storage.session.set({
|
|
1238
1249
|
codeVerifier: t,
|
|
1239
|
-
state:
|
|
1250
|
+
state: n,
|
|
1240
1251
|
authInProgress: !0
|
|
1241
1252
|
});
|
|
1242
1253
|
const o = chrome.identity.getRedirectURL("callback"), s = new URL(this.authEndpoints.authorize);
|
|
1243
|
-
return s.searchParams.set("client_id", this.authClientId), s.searchParams.set("response_type", "code"), s.searchParams.set("redirect_uri", o), s.searchParams.set("scope", e), s.searchParams.set("code_challenge", r), s.searchParams.set("code_challenge_method", "S256"), s.searchParams.set("state",
|
|
1254
|
+
return s.searchParams.set("client_id", this.authClientId), s.searchParams.set("response_type", "code"), s.searchParams.set("redirect_uri", o), s.searchParams.set("scope", e), s.searchParams.set("code_challenge", r), s.searchParams.set("code_challenge_method", "S256"), s.searchParams.set("state", n), new Promise((i, h) => {
|
|
1244
1255
|
chrome.identity.launchWebAuthFlow(
|
|
1245
1256
|
{ url: s.toString(), interactive: !0 },
|
|
1246
1257
|
async (a) => {
|
|
@@ -1253,8 +1264,8 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1253
1264
|
return;
|
|
1254
1265
|
}
|
|
1255
1266
|
try {
|
|
1256
|
-
const
|
|
1257
|
-
if (
|
|
1267
|
+
const E = new URL(a), d = E.searchParams.get("code"), u = E.searchParams.get("state"), { state: g } = await chrome.storage.session.get("state");
|
|
1268
|
+
if (u !== g) {
|
|
1258
1269
|
await chrome.storage.session.remove(["codeVerifier", "state"]), h(l("oauth_error", "State mismatch"));
|
|
1259
1270
|
return;
|
|
1260
1271
|
}
|
|
@@ -1263,12 +1274,12 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1263
1274
|
return;
|
|
1264
1275
|
}
|
|
1265
1276
|
await this.exchangeCodeForTokens(d), await chrome.storage.session.remove(["codeVerifier", "state"]);
|
|
1266
|
-
const
|
|
1267
|
-
if (
|
|
1277
|
+
const m = await this.getAuthState();
|
|
1278
|
+
if (m.status !== "authenticated")
|
|
1268
1279
|
throw l("oauth_error", "Login failed");
|
|
1269
|
-
|
|
1270
|
-
} catch (
|
|
1271
|
-
await chrome.storage.session.remove(["codeVerifier", "state"]), h(
|
|
1280
|
+
i(m);
|
|
1281
|
+
} catch (E) {
|
|
1282
|
+
await chrome.storage.session.remove(["codeVerifier", "state"]), h(E);
|
|
1272
1283
|
}
|
|
1273
1284
|
}
|
|
1274
1285
|
);
|
|
@@ -1284,7 +1295,7 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1284
1295
|
*/
|
|
1285
1296
|
async sendExtRequest(e, t) {
|
|
1286
1297
|
const r = await this.sendExtRequestRaw(e, t);
|
|
1287
|
-
if (
|
|
1298
|
+
if (I(r.response))
|
|
1288
1299
|
throw this.logger.error("[BodhiExtClient] Extension error:", r.response.error), new Error(
|
|
1289
1300
|
r.response.error.message || `Extension request failed: ${JSON.stringify(r.response)}`
|
|
1290
1301
|
);
|
|
@@ -1298,7 +1309,7 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1298
1309
|
* @param headers Optional headers
|
|
1299
1310
|
* @returns API response from LLM server via bodhi-browser-ext
|
|
1300
1311
|
*/
|
|
1301
|
-
async sendApiRequest(e, t, r,
|
|
1312
|
+
async sendApiRequest(e, t, r, n) {
|
|
1302
1313
|
if (!this.extensionId)
|
|
1303
1314
|
throw new T(
|
|
1304
1315
|
"not_initialized",
|
|
@@ -1315,10 +1326,10 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1315
1326
|
method: e,
|
|
1316
1327
|
endpoint: t,
|
|
1317
1328
|
body: r,
|
|
1318
|
-
headers:
|
|
1329
|
+
headers: n
|
|
1319
1330
|
}
|
|
1320
1331
|
};
|
|
1321
|
-
return this.logger.debug(`[BodhiExtClient] Request ID: ${o}, Extension: ${this.extensionId}`), new Promise((
|
|
1332
|
+
return this.logger.debug(`[BodhiExtClient] Request ID: ${o}, Extension: ${this.extensionId}`), new Promise((i, h) => {
|
|
1322
1333
|
try {
|
|
1323
1334
|
chrome.runtime.sendMessage(this.extensionId, s, (a) => {
|
|
1324
1335
|
if (chrome.runtime.lastError) {
|
|
@@ -1339,7 +1350,7 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1339
1350
|
}
|
|
1340
1351
|
a.type === _.API_RESPONSE && a.requestId === o ? "error" in a ? (this.logger.error(`[BodhiExtClient] API error for ${o}:`, a.error), h(
|
|
1341
1352
|
new T(a.error.type || "extension_error", a.error.message)
|
|
1342
|
-
)) : (this.logger.debug(`[BodhiExtClient] ✓ Valid API_RESPONSE for ${o}`),
|
|
1353
|
+
)) : (this.logger.debug(`[BodhiExtClient] ✓ Valid API_RESPONSE for ${o}`), i(a.response)) : (this.logger.error(
|
|
1343
1354
|
`[BodhiExtClient] Invalid response format for ${o}:`,
|
|
1344
1355
|
a
|
|
1345
1356
|
), h(new T("extension_error", "Invalid response format")));
|
|
@@ -1365,7 +1376,7 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1365
1376
|
`[BodhiExtClient] Sending EXT_REQUEST (raw): action=${e}`,
|
|
1366
1377
|
t ? { params: t } : ""
|
|
1367
1378
|
);
|
|
1368
|
-
const r = crypto.randomUUID(),
|
|
1379
|
+
const r = crypto.randomUUID(), n = {
|
|
1369
1380
|
type: _.EXT_REQUEST,
|
|
1370
1381
|
requestId: r,
|
|
1371
1382
|
request: {
|
|
@@ -1375,7 +1386,7 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1375
1386
|
};
|
|
1376
1387
|
return this.logger.debug(`[BodhiExtClient] Request ID: ${r}, Extension: ${this.extensionId}`), new Promise((o, s) => {
|
|
1377
1388
|
try {
|
|
1378
|
-
chrome.runtime.sendMessage(this.extensionId,
|
|
1389
|
+
chrome.runtime.sendMessage(this.extensionId, n, (i) => {
|
|
1379
1390
|
if (chrome.runtime.lastError) {
|
|
1380
1391
|
this.logger.error(
|
|
1381
1392
|
`[BodhiExtClient] Chrome runtime error for request ${r}:`,
|
|
@@ -1383,135 +1394,116 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1383
1394
|
), s(new Error(chrome.runtime.lastError.message));
|
|
1384
1395
|
return;
|
|
1385
1396
|
}
|
|
1386
|
-
if (this.logger.debug(`[BodhiExtClient] Response for request ${r}:`,
|
|
1397
|
+
if (this.logger.debug(`[BodhiExtClient] Response for request ${r}:`, i), !i) {
|
|
1387
1398
|
this.logger.error(`[BodhiExtClient] No response received for request ${r}`), s(new Error("No response from extension"));
|
|
1388
1399
|
return;
|
|
1389
1400
|
}
|
|
1390
|
-
|
|
1401
|
+
i.type === _.EXT_RESPONSE && i.requestId === r ? (this.logger.debug(`[BodhiExtClient] ✓ Valid EXT_RESPONSE for ${r}`), o(i)) : (this.logger.error(
|
|
1391
1402
|
`[BodhiExtClient] Invalid response format for ${r}:`,
|
|
1392
|
-
|
|
1403
|
+
i
|
|
1393
1404
|
), s(new T("extension_error", "Invalid response format")));
|
|
1394
1405
|
});
|
|
1395
|
-
} catch (
|
|
1396
|
-
this.logger.error(`[BodhiExtClient] Exception sending message for ${r}:`,
|
|
1406
|
+
} catch (i) {
|
|
1407
|
+
this.logger.error(`[BodhiExtClient] Exception sending message for ${r}:`, i), s(i);
|
|
1397
1408
|
}
|
|
1398
1409
|
});
|
|
1399
1410
|
}
|
|
1400
1411
|
/**
|
|
1401
|
-
*
|
|
1402
|
-
*
|
|
1403
|
-
* @param uiPort Port connected from UI
|
|
1404
|
-
* @param message Stream request message from UI
|
|
1412
|
+
* Register a chrome.runtime.onConnect listener for a streaming port.
|
|
1413
|
+
* Validates port name and message type, then delegates to handler.
|
|
1405
1414
|
*/
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1415
|
+
registerStreamPortListener(e, t, r, n) {
|
|
1416
|
+
chrome.runtime.onConnect.addListener((o) => {
|
|
1417
|
+
o.name === e && (this.logger.info(`[BodhiExtClient] Port connected: ${e}`), o.onMessage.addListener(async (s) => {
|
|
1418
|
+
if (s.type !== t) {
|
|
1419
|
+
this.logger.warn(`[BodhiExtClient] Unknown message type on ${e}:`, s.type), o.postMessage({
|
|
1420
|
+
type: r,
|
|
1421
|
+
requestId: s.requestId,
|
|
1422
|
+
error: { message: "Unknown message type", type: "extension_error" }
|
|
1423
|
+
});
|
|
1424
|
+
return;
|
|
1425
|
+
}
|
|
1426
|
+
await n(o, s);
|
|
1427
|
+
}), o.onDisconnect.addListener(() => {
|
|
1428
|
+
this.logger.info(`[BodhiExtClient] Port disconnected: ${e}`);
|
|
1429
|
+
}));
|
|
1420
1430
|
});
|
|
1431
|
+
}
|
|
1432
|
+
/**
|
|
1433
|
+
* Generic stream relay: validates auth, connects to bodhi-browser-ext,
|
|
1434
|
+
* sets up timeout/disconnect handling, and delegates message forwarding
|
|
1435
|
+
* to the onBodhiMessage callback.
|
|
1436
|
+
*
|
|
1437
|
+
* @param onBodhiMessage Called for each message from bodhi-browser-ext.
|
|
1438
|
+
* Returns true if the stream is complete (triggers cleanup).
|
|
1439
|
+
*/
|
|
1440
|
+
async handleGenericStreamRelay(e, t, r, n, o, s, i) {
|
|
1441
|
+
if (this.logger.debug("[BodhiExtClient] Processing stream relay:", {
|
|
1442
|
+
requestId: t,
|
|
1443
|
+
method: r.method,
|
|
1444
|
+
endpoint: r.endpoint,
|
|
1445
|
+
bodhiPortName: n
|
|
1446
|
+
}), !this.extensionId) {
|
|
1447
|
+
e.postMessage({
|
|
1448
|
+
type: s,
|
|
1449
|
+
requestId: t,
|
|
1450
|
+
error: { message: "Client not initialized (no extensionId)", type: "extension_error" }
|
|
1451
|
+
});
|
|
1452
|
+
return;
|
|
1453
|
+
}
|
|
1421
1454
|
try {
|
|
1422
|
-
let
|
|
1423
|
-
if (
|
|
1424
|
-
const
|
|
1425
|
-
if (!
|
|
1455
|
+
let h = { ...r.headers };
|
|
1456
|
+
if (r.authenticated !== !1) {
|
|
1457
|
+
const u = await this._getAccessTokenRaw();
|
|
1458
|
+
if (!u) {
|
|
1426
1459
|
e.postMessage({
|
|
1427
|
-
type:
|
|
1428
|
-
requestId:
|
|
1429
|
-
error: {
|
|
1430
|
-
message: "Not authenticated. Please log in first.",
|
|
1431
|
-
type: "extension_error"
|
|
1432
|
-
}
|
|
1460
|
+
type: s,
|
|
1461
|
+
requestId: t,
|
|
1462
|
+
error: { message: "Not authenticated. Please log in first.", type: "extension_error" }
|
|
1433
1463
|
});
|
|
1434
1464
|
return;
|
|
1435
1465
|
}
|
|
1436
|
-
|
|
1437
|
-
...u,
|
|
1438
|
-
Authorization: `Bearer ${E}`
|
|
1439
|
-
}, this.logger.debug("[BodhiExtClient] Injected auth token for authenticated request");
|
|
1466
|
+
h = { ...h, Authorization: `Bearer ${u}` }, this.logger.debug("[BodhiExtClient] Injected auth token for stream relay");
|
|
1440
1467
|
}
|
|
1441
|
-
const
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
type:
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
if (te(E)) {
|
|
1457
|
-
const I = E.response, q = I.body;
|
|
1458
|
-
I.status >= 400 ? e.postMessage({
|
|
1459
|
-
type: c.EXT2EXT_CLIENT_STREAM_API_ERROR,
|
|
1460
|
-
requestId: r,
|
|
1461
|
-
response: I
|
|
1462
|
-
}) : q?.done ? (e.postMessage({
|
|
1463
|
-
type: c.EXT2EXT_CLIENT_STREAM_DONE,
|
|
1464
|
-
requestId: r
|
|
1465
|
-
}), this.logger.info(`[BodhiExtClient] Stream complete for ${r}`), clearTimeout(g), this.cleanupStreamPort(r)) : e.postMessage({
|
|
1466
|
-
type: c.EXT2EXT_CLIENT_STREAM_CHUNK,
|
|
1467
|
-
requestId: r,
|
|
1468
|
-
response: I
|
|
1469
|
-
});
|
|
1470
|
-
} else re(E) ? (this.logger.error(
|
|
1471
|
-
`[BodhiExtClient] Stream API error for ${r}: ${E.response.status}`
|
|
1472
|
-
), e.postMessage({
|
|
1473
|
-
type: c.EXT2EXT_CLIENT_STREAM_API_ERROR,
|
|
1474
|
-
requestId: r,
|
|
1475
|
-
response: E.response
|
|
1476
|
-
})) : se(E) && (this.logger.error(
|
|
1477
|
-
`[BodhiExtClient] Stream error for ${r}:`,
|
|
1478
|
-
E.error.message
|
|
1479
|
-
), e.postMessage({
|
|
1480
|
-
type: c.EXT2EXT_CLIENT_STREAM_ERROR,
|
|
1481
|
-
requestId: r,
|
|
1482
|
-
error: {
|
|
1483
|
-
message: `stream error: ${JSON.stringify(E)}`,
|
|
1484
|
-
type: "extension_error"
|
|
1485
|
-
}
|
|
1486
|
-
}), clearTimeout(g), this.cleanupStreamPort(r));
|
|
1487
|
-
}), d.onDisconnect.addListener(() => {
|
|
1488
|
-
clearTimeout(g), this.activeStreamPorts.has(r) && (this.logger.error(`[BodhiExtClient] Bodhi port disconnected for ${r}`), e.postMessage({
|
|
1489
|
-
type: c.EXT2EXT_CLIENT_STREAM_ERROR,
|
|
1490
|
-
requestId: r,
|
|
1468
|
+
const a = chrome.runtime.connect(this.extensionId, { name: n });
|
|
1469
|
+
this.activeStreamPorts.set(t, a);
|
|
1470
|
+
const E = setTimeout(() => {
|
|
1471
|
+
this.activeStreamPorts.has(t) && (this.logger.error(`[BodhiExtClient] Stream timeout for ${t}`), e.postMessage({
|
|
1472
|
+
type: s,
|
|
1473
|
+
requestId: t,
|
|
1474
|
+
error: { message: "Stream request timed out", type: "timeout_error" }
|
|
1475
|
+
}), this.cleanupStreamPort(t));
|
|
1476
|
+
}, S.STREAM_TIMEOUT);
|
|
1477
|
+
a.onMessage.addListener((u) => {
|
|
1478
|
+
i(u, e, t) && (clearTimeout(E), this.cleanupStreamPort(t));
|
|
1479
|
+
}), a.onDisconnect.addListener(() => {
|
|
1480
|
+
clearTimeout(E), this.activeStreamPorts.has(t) && (this.logger.error(`[BodhiExtClient] Bodhi port disconnected for ${t}`), e.postMessage({
|
|
1481
|
+
type: s,
|
|
1482
|
+
requestId: t,
|
|
1491
1483
|
error: {
|
|
1492
1484
|
message: "Connection to Bodhi extension closed unexpectedly",
|
|
1493
1485
|
type: "network_error"
|
|
1494
1486
|
}
|
|
1495
|
-
}), this.activeStreamPorts.delete(
|
|
1487
|
+
}), this.activeStreamPorts.delete(t));
|
|
1496
1488
|
});
|
|
1497
|
-
const
|
|
1498
|
-
type:
|
|
1499
|
-
requestId:
|
|
1489
|
+
const d = {
|
|
1490
|
+
type: o,
|
|
1491
|
+
requestId: t,
|
|
1500
1492
|
request: {
|
|
1501
|
-
method:
|
|
1502
|
-
endpoint:
|
|
1503
|
-
body:
|
|
1504
|
-
headers:
|
|
1493
|
+
method: r.method,
|
|
1494
|
+
endpoint: r.endpoint,
|
|
1495
|
+
body: r.body,
|
|
1496
|
+
headers: h
|
|
1505
1497
|
}
|
|
1506
1498
|
};
|
|
1507
|
-
this.logger.debug("[BodhiExtClient] Sending stream request to bodhi port:",
|
|
1508
|
-
} catch (
|
|
1509
|
-
const
|
|
1510
|
-
this.logger.error("[BodhiExtClient] Stream error:", JSON.stringify(
|
|
1511
|
-
type:
|
|
1512
|
-
requestId:
|
|
1499
|
+
this.logger.debug("[BodhiExtClient] Sending stream request to bodhi port:", d), a.postMessage(d);
|
|
1500
|
+
} catch (h) {
|
|
1501
|
+
const a = h;
|
|
1502
|
+
this.logger.error("[BodhiExtClient] Stream relay error:", JSON.stringify(a.message)), e.postMessage({
|
|
1503
|
+
type: s,
|
|
1504
|
+
requestId: t,
|
|
1513
1505
|
error: {
|
|
1514
|
-
message: `uncaught error: ${JSON.stringify({ error:
|
|
1506
|
+
message: `uncaught error: ${JSON.stringify({ error: a, message: a.message })}`,
|
|
1515
1507
|
type: "extension_error"
|
|
1516
1508
|
}
|
|
1517
1509
|
});
|
|
@@ -1530,6 +1522,105 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1530
1522
|
this.activeStreamPorts.delete(e);
|
|
1531
1523
|
}
|
|
1532
1524
|
}
|
|
1525
|
+
/**
|
|
1526
|
+
* Handle SSE-parsed streaming request — translates STREAM_* messages to EXT2EXT_CLIENT_STREAM_*
|
|
1527
|
+
*/
|
|
1528
|
+
async handleStreamRequest(e, t) {
|
|
1529
|
+
const { requestId: r, request: n } = t;
|
|
1530
|
+
await this.handleGenericStreamRelay(
|
|
1531
|
+
e,
|
|
1532
|
+
r,
|
|
1533
|
+
n,
|
|
1534
|
+
se,
|
|
1535
|
+
_.STREAM_REQUEST,
|
|
1536
|
+
c.EXT2EXT_CLIENT_STREAM_ERROR,
|
|
1537
|
+
(o, s, i) => {
|
|
1538
|
+
if (oe(o)) {
|
|
1539
|
+
const h = o.response, a = h.body;
|
|
1540
|
+
return h.status >= 400 ? (s.postMessage({
|
|
1541
|
+
type: c.EXT2EXT_CLIENT_STREAM_API_ERROR,
|
|
1542
|
+
requestId: i,
|
|
1543
|
+
response: h
|
|
1544
|
+
}), !1) : a?.done ? (s.postMessage({
|
|
1545
|
+
type: c.EXT2EXT_CLIENT_STREAM_DONE,
|
|
1546
|
+
requestId: i
|
|
1547
|
+
}), this.logger.info(`[BodhiExtClient] Stream complete for ${i}`), !0) : (s.postMessage({
|
|
1548
|
+
type: c.EXT2EXT_CLIENT_STREAM_CHUNK,
|
|
1549
|
+
requestId: i,
|
|
1550
|
+
response: h
|
|
1551
|
+
}), !1);
|
|
1552
|
+
} else {
|
|
1553
|
+
if (ne(o))
|
|
1554
|
+
return this.logger.error(
|
|
1555
|
+
`[BodhiExtClient] Stream API error for ${i}: ${o.response.status}`
|
|
1556
|
+
), s.postMessage({
|
|
1557
|
+
type: c.EXT2EXT_CLIENT_STREAM_API_ERROR,
|
|
1558
|
+
requestId: i,
|
|
1559
|
+
response: o.response
|
|
1560
|
+
}), !1;
|
|
1561
|
+
if (ie(o))
|
|
1562
|
+
return this.logger.error(
|
|
1563
|
+
`[BodhiExtClient] Stream error for ${i}:`,
|
|
1564
|
+
o.error.message
|
|
1565
|
+
), s.postMessage({
|
|
1566
|
+
type: c.EXT2EXT_CLIENT_STREAM_ERROR,
|
|
1567
|
+
requestId: i,
|
|
1568
|
+
error: {
|
|
1569
|
+
message: `stream error: ${JSON.stringify(o)}`,
|
|
1570
|
+
type: "extension_error"
|
|
1571
|
+
}
|
|
1572
|
+
}), !0;
|
|
1573
|
+
}
|
|
1574
|
+
return !1;
|
|
1575
|
+
}
|
|
1576
|
+
);
|
|
1577
|
+
}
|
|
1578
|
+
/**
|
|
1579
|
+
* Handle raw text streaming request — translates STREAM_TEXT_* messages to EXT2EXT_CLIENT_STREAM_TEXT_*
|
|
1580
|
+
*/
|
|
1581
|
+
async handleStreamTextRequest(e, t) {
|
|
1582
|
+
const { requestId: r, request: n } = t;
|
|
1583
|
+
await this.handleGenericStreamRelay(
|
|
1584
|
+
e,
|
|
1585
|
+
r,
|
|
1586
|
+
n,
|
|
1587
|
+
ae,
|
|
1588
|
+
_.STREAM_TEXT_REQUEST,
|
|
1589
|
+
c.EXT2EXT_CLIENT_STREAM_TEXT_ERROR,
|
|
1590
|
+
(o, s, i) => {
|
|
1591
|
+
switch (o.type) {
|
|
1592
|
+
case _.STREAM_TEXT_START:
|
|
1593
|
+
return s.postMessage({
|
|
1594
|
+
type: c.EXT2EXT_CLIENT_STREAM_TEXT_START,
|
|
1595
|
+
requestId: i,
|
|
1596
|
+
status: o.status,
|
|
1597
|
+
headers: o.headers
|
|
1598
|
+
}), !1;
|
|
1599
|
+
case _.STREAM_TEXT_CHUNK:
|
|
1600
|
+
return s.postMessage({
|
|
1601
|
+
type: c.EXT2EXT_CLIENT_STREAM_TEXT_CHUNK,
|
|
1602
|
+
requestId: i,
|
|
1603
|
+
chunk: o.chunk
|
|
1604
|
+
}), !1;
|
|
1605
|
+
case _.STREAM_TEXT_DONE:
|
|
1606
|
+
return this.logger.info(`[BodhiExtClient] Stream text complete for ${i}`), s.postMessage({
|
|
1607
|
+
type: c.EXT2EXT_CLIENT_STREAM_TEXT_DONE,
|
|
1608
|
+
requestId: i
|
|
1609
|
+
}), !0;
|
|
1610
|
+
case _.STREAM_TEXT_ERROR:
|
|
1611
|
+
return this.logger.error(
|
|
1612
|
+
`[BodhiExtClient] Stream text error for ${i}:`,
|
|
1613
|
+
o.error.message
|
|
1614
|
+
), s.postMessage({
|
|
1615
|
+
type: c.EXT2EXT_CLIENT_STREAM_TEXT_ERROR,
|
|
1616
|
+
requestId: i,
|
|
1617
|
+
error: o.error
|
|
1618
|
+
}), !0;
|
|
1619
|
+
}
|
|
1620
|
+
return !1;
|
|
1621
|
+
}
|
|
1622
|
+
);
|
|
1623
|
+
}
|
|
1533
1624
|
// ============================================================================
|
|
1534
1625
|
// Token Management (Private Methods)
|
|
1535
1626
|
// ============================================================================
|
|
@@ -1575,7 +1666,7 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1575
1666
|
async _doRefreshToken(e) {
|
|
1576
1667
|
this.logger.debug("Refreshing access token");
|
|
1577
1668
|
try {
|
|
1578
|
-
const t = await
|
|
1669
|
+
const t = await ee(
|
|
1579
1670
|
this.authEndpoints.token,
|
|
1580
1671
|
e,
|
|
1581
1672
|
this.authClientId
|
|
@@ -1615,29 +1706,32 @@ const Ee = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1615
1706
|
]);
|
|
1616
1707
|
}
|
|
1617
1708
|
parseJwt(e) {
|
|
1618
|
-
const r = e.split(".")[1].replace(/-/g, "+").replace(/_/g, "/"),
|
|
1709
|
+
const r = e.split(".")[1].replace(/-/g, "+").replace(/_/g, "/"), n = decodeURIComponent(
|
|
1619
1710
|
atob(r).split("").map((o) => "%" + ("00" + o.charCodeAt(0).toString(16)).slice(-2)).join("")
|
|
1620
1711
|
);
|
|
1621
|
-
return JSON.parse(
|
|
1712
|
+
return JSON.parse(n);
|
|
1622
1713
|
}
|
|
1623
1714
|
createErrorClientNotInitialized(e) {
|
|
1624
1715
|
return `Client not initialized. Extension discovery not triggered nor extensionId set, cannot handle request: ${JSON.stringify(e)}`;
|
|
1625
1716
|
}
|
|
1626
1717
|
};
|
|
1627
|
-
|
|
1628
|
-
let
|
|
1629
|
-
const
|
|
1718
|
+
S.STREAM_TIMEOUT = 6e4;
|
|
1719
|
+
let w = S;
|
|
1720
|
+
const ye = "production";
|
|
1630
1721
|
export {
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1722
|
+
w as BodhiExtClient,
|
|
1723
|
+
Te as ChromeSessionStorageAdapter,
|
|
1724
|
+
de as DEFAULT_API_TIMEOUT_MS,
|
|
1725
|
+
he as DISCOVERY_ATTEMPTS,
|
|
1726
|
+
ue as DISCOVERY_ATTEMPT_TIMEOUT,
|
|
1727
|
+
Ee as DISCOVERY_ATTEMPT_WAIT_MS,
|
|
1728
|
+
ce as DISCOVERY_TIMEOUT_MS,
|
|
1729
|
+
p as EXT2EXT_CLIENT_ACTIONS,
|
|
1638
1730
|
c as EXT2EXT_CLIENT_MESSAGE_TYPES,
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1731
|
+
M as EXT2EXT_CLIENT_STREAM_PORT,
|
|
1732
|
+
O as EXT2EXT_CLIENT_STREAM_TEXT_PORT,
|
|
1733
|
+
ye as EXT_BUILD_MODE,
|
|
1734
|
+
fe as ExtUIClient,
|
|
1735
|
+
Ce as InMemoryStorage,
|
|
1736
|
+
le as isExtClientApiError
|
|
1643
1737
|
};
|