@aexol/spectral 0.9.87 → 0.9.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-helper.d.ts","sourceRoot":"","sources":["../src/auth-helper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,aAAa,CAAC;AAOrB,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA8FD;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,MAAM,CAAC,EAAE,MAAM,EACf,SAAS,GAAE,MAAyB,GACnC,OAAO,CAAC,WAAW,CAAC,CA8DtB;AAMD,0EAA0E;AAC1E,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAUjD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,gBAAgB,CAAC,
|
|
1
|
+
{"version":3,"file":"auth-helper.d.ts","sourceRoot":"","sources":["../src/auth-helper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,aAAa,CAAC;AAOrB,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA8FD;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,MAAM,CAAC,EAAE,MAAM,EACf,SAAS,GAAE,MAAyB,GACnC,OAAO,CAAC,WAAW,CAAC,CA8DtB;AAMD,0EAA0E;AAC1E,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAUjD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAgErE"}
|
package/dist/auth-helper.js
CHANGED
|
@@ -193,7 +193,22 @@ export async function ensureAuthenticated() {
|
|
|
193
193
|
if (token) {
|
|
194
194
|
// If the stored user JWT is locally known to be expired, skip the network roundtrip
|
|
195
195
|
if (existingCfg?.userJwt && isJwtExpired(existingCfg.userJwt)) {
|
|
196
|
-
//
|
|
196
|
+
// userJwt expired — if we have a teamApiKey, try that before re-auth
|
|
197
|
+
if (existingCfg?.teamApiKey) {
|
|
198
|
+
try {
|
|
199
|
+
const client = new AexolMcpClient(apiUrl, existingCfg.teamApiKey);
|
|
200
|
+
await client.listTools();
|
|
201
|
+
return { ok: true, config: existingCfg };
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
if (!isAuthError(err)) {
|
|
205
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
206
|
+
return { ok: false, config: existingCfg, reason: `Backend unreachable: ${msg}` };
|
|
207
|
+
}
|
|
208
|
+
// teamApiKey also failed — fall through to OAuth
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// no teamApiKey — fall through to OAuth
|
|
197
212
|
}
|
|
198
213
|
else {
|
|
199
214
|
try {
|
|
@@ -24,6 +24,7 @@ export declare class BrowserService {
|
|
|
24
24
|
private pendingDialogs;
|
|
25
25
|
private _recording;
|
|
26
26
|
private closePromise;
|
|
27
|
+
private launchLock;
|
|
27
28
|
constructor(config?: Partial<BrowserConfig>);
|
|
28
29
|
static getInstance(config?: Partial<BrowserConfig>): BrowserService;
|
|
29
30
|
static resetInstance(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-service.d.ts","sourceRoot":"","sources":["../../../src/extensions/browser/browser-service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAkB,MAAM,YAAY,CAAC;AAChF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAsBjD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAQD,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,aAAa,CAA8D;IACnF,OAAO,CAAC,aAAa,CAA0C;IAC/D,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,cAAc,CAKd;IACR,OAAO,CAAC,UAAU,CAA0F;IAC5G,OAAO,CAAC,YAAY,CAA8B;
|
|
1
|
+
{"version":3,"file":"browser-service.d.ts","sourceRoot":"","sources":["../../../src/extensions/browser/browser-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -38,6 +38,7 @@ export class BrowserService {
|
|
|
38
38
|
pendingDialogs = [];
|
|
39
39
|
_recording = null;
|
|
40
40
|
closePromise = null;
|
|
41
|
+
launchLock = null;
|
|
41
42
|
constructor(config) {
|
|
42
43
|
this.config = { ...getBrowserConfig(), ...config };
|
|
43
44
|
}
|
|
@@ -119,50 +120,67 @@ export class BrowserService {
|
|
|
119
120
|
}
|
|
120
121
|
}
|
|
121
122
|
async ensureBrowser() {
|
|
123
|
+
// Serialize launches — if a launch is in progress, wait for it
|
|
124
|
+
if (this.launchLock) {
|
|
125
|
+
await this.launchLock;
|
|
126
|
+
if (this.browser?.isConnected() && this.context && this.pages.length > 0) {
|
|
127
|
+
const page = this.pages[this.activePageIndex];
|
|
128
|
+
return { browser: this.browser, context: this.context, page };
|
|
129
|
+
}
|
|
130
|
+
}
|
|
122
131
|
if (this.browser?.isConnected() && this.context && this.pages.length > 0) {
|
|
123
132
|
const page = this.pages[this.activePageIndex];
|
|
124
133
|
return { browser: this.browser, context: this.context, page };
|
|
125
134
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
135
|
+
const doLaunch = async () => {
|
|
136
|
+
await this.close();
|
|
137
|
+
const pw = loadPlaywright();
|
|
138
|
+
const launchOptions = {
|
|
139
|
+
headless: this.config.headless,
|
|
140
|
+
args: [
|
|
141
|
+
"--no-sandbox",
|
|
142
|
+
"--disable-setuid-sandbox",
|
|
143
|
+
"--disable-dev-shm-usage",
|
|
144
|
+
],
|
|
145
|
+
};
|
|
146
|
+
switch (this.config.browserName) {
|
|
147
|
+
case "firefox":
|
|
148
|
+
this.browser = await pw.firefox.launch(launchOptions);
|
|
149
|
+
break;
|
|
150
|
+
case "webkit":
|
|
151
|
+
this.browser = await pw.webkit.launch(launchOptions);
|
|
152
|
+
break;
|
|
153
|
+
default:
|
|
154
|
+
this.browser = await pw.chromium.launch(launchOptions);
|
|
155
|
+
}
|
|
156
|
+
this.context = await this.browser.newContext({
|
|
157
|
+
viewport: this.config.viewport,
|
|
158
|
+
});
|
|
159
|
+
this.context.on("page", (page) => {
|
|
160
|
+
page.on("console", (msg) => {
|
|
161
|
+
this.consoleBuffer.push({
|
|
162
|
+
type: msg.type(),
|
|
163
|
+
text: msg.text(),
|
|
164
|
+
pageUrl: page.url(),
|
|
165
|
+
});
|
|
155
166
|
});
|
|
167
|
+
this.trackNetworkRequest(page);
|
|
168
|
+
this.installDialogInterceptor(page);
|
|
156
169
|
});
|
|
170
|
+
const page = await this.context.newPage();
|
|
157
171
|
this.trackNetworkRequest(page);
|
|
158
172
|
this.installDialogInterceptor(page);
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
this.
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
173
|
+
this.pages = [page];
|
|
174
|
+
this.activePageIndex = 0;
|
|
175
|
+
};
|
|
176
|
+
this.launchLock = doLaunch();
|
|
177
|
+
try {
|
|
178
|
+
await this.launchLock;
|
|
179
|
+
return { browser: this.browser, context: this.context, page: this.pages[0] };
|
|
180
|
+
}
|
|
181
|
+
finally {
|
|
182
|
+
this.launchLock = null;
|
|
183
|
+
}
|
|
166
184
|
}
|
|
167
185
|
getBrowser() {
|
|
168
186
|
if (!this.browser?.isConnected())
|
|
@@ -333,29 +351,32 @@ export class BrowserService {
|
|
|
333
351
|
if (this.closePromise)
|
|
334
352
|
return this.closePromise;
|
|
335
353
|
this.closePromise = (async () => {
|
|
336
|
-
|
|
354
|
+
const withTimeout = async (promise, ms, label) => {
|
|
337
355
|
try {
|
|
338
|
-
await
|
|
356
|
+
return await Promise.race([
|
|
357
|
+
promise,
|
|
358
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(`Timed out after ${ms}ms: ${label}`)), ms))
|
|
359
|
+
]);
|
|
339
360
|
}
|
|
340
|
-
catch {
|
|
361
|
+
catch (e) {
|
|
362
|
+
process.stderr.write(`[browser] close ${label}: ${e.message}\n`);
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
const closeTimeout = 5000; // 5 seconds per operation
|
|
366
|
+
for (const page of [...this.pages]) {
|
|
367
|
+
await withTimeout(page.close().catch(() => { }), closeTimeout, 'page.close()');
|
|
341
368
|
}
|
|
342
369
|
this.pages = [];
|
|
343
370
|
this.activePageIndex = 0;
|
|
344
371
|
const context = this.context;
|
|
345
372
|
this.context = null;
|
|
346
373
|
if (context) {
|
|
347
|
-
|
|
348
|
-
await context.close();
|
|
349
|
-
}
|
|
350
|
-
catch { /* already closed */ }
|
|
374
|
+
await withTimeout(context.close().catch(() => { }), closeTimeout, 'context.close()');
|
|
351
375
|
}
|
|
352
376
|
const browser = this.browser;
|
|
353
377
|
this.browser = null;
|
|
354
378
|
if (browser) {
|
|
355
|
-
|
|
356
|
-
await browser.close();
|
|
357
|
-
}
|
|
358
|
-
catch { /* already closed */ }
|
|
379
|
+
await withTimeout(browser.close().catch(() => { }), closeTimeout, 'browser.close()');
|
|
359
380
|
}
|
|
360
381
|
this._recording = null;
|
|
361
382
|
})().finally(() => {
|