@quanta-intellect/vessel-browser 0.1.127 → 0.1.128
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/out/main/index.js +446 -461
- package/out/preload/content-script.js +39 -2
- package/out/renderer/assets/{index-CwDcicSR.css → index-BhKMoOd-.css} +767 -29
- package/out/renderer/assets/{index-DW3ChyZf.js → index-Dwhz26u8.js} +369 -1073
- package/out/renderer/index.html +2 -2
- package/package.json +10 -1
package/out/main/index.js
CHANGED
|
@@ -120,6 +120,9 @@ let settings = null;
|
|
|
120
120
|
let settingsIssues = [];
|
|
121
121
|
let saveTimer = null;
|
|
122
122
|
let saveDirty = false;
|
|
123
|
+
function isMissingFileError(err) {
|
|
124
|
+
return typeof err === "object" && err !== null && "code" in err && err.code === "ENOENT";
|
|
125
|
+
}
|
|
123
126
|
function getUserDataPath() {
|
|
124
127
|
if (typeof electron.app?.getPath === "function") {
|
|
125
128
|
return electron.app.getPath("userData");
|
|
@@ -135,7 +138,8 @@ function getChatProviderSecretPath() {
|
|
|
135
138
|
function canUseSafeStorage$1() {
|
|
136
139
|
try {
|
|
137
140
|
return electron.safeStorage.isEncryptionAvailable();
|
|
138
|
-
} catch {
|
|
141
|
+
} catch (err) {
|
|
142
|
+
logger$t.warn("safeStorage.isEncryptionAvailable() failed, assuming unavailable:", err);
|
|
139
143
|
return false;
|
|
140
144
|
}
|
|
141
145
|
}
|
|
@@ -143,7 +147,8 @@ function writePrivateFile(filePath2, data) {
|
|
|
143
147
|
fs.writeFileSync(filePath2, data, { mode: 384 });
|
|
144
148
|
try {
|
|
145
149
|
fs.chmodSync(filePath2, 384);
|
|
146
|
-
} catch {
|
|
150
|
+
} catch (err) {
|
|
151
|
+
logger$t.debug("Could not chmod private file (non-POSIX filesystem):", err);
|
|
147
152
|
}
|
|
148
153
|
}
|
|
149
154
|
function assertSafeStorageAvailable() {
|
|
@@ -160,7 +165,10 @@ function readStoredProviderSecret() {
|
|
|
160
165
|
if (parsed && typeof parsed === "object" && typeof parsed.providerId === "string" && typeof parsed.apiKey === "string") {
|
|
161
166
|
return parsed;
|
|
162
167
|
}
|
|
163
|
-
} catch {
|
|
168
|
+
} catch (err) {
|
|
169
|
+
if (!isMissingFileError(err)) {
|
|
170
|
+
logger$t.warn("Could not read stored provider secret:", err);
|
|
171
|
+
}
|
|
164
172
|
}
|
|
165
173
|
return null;
|
|
166
174
|
}
|
|
@@ -175,7 +183,10 @@ function writeStoredProviderSecret(secret) {
|
|
|
175
183
|
function clearStoredProviderSecret() {
|
|
176
184
|
try {
|
|
177
185
|
fs.unlinkSync(getChatProviderSecretPath());
|
|
178
|
-
} catch {
|
|
186
|
+
} catch (err) {
|
|
187
|
+
if (!isMissingFileError(err)) {
|
|
188
|
+
logger$t.warn("Could not delete provider secret file:", err);
|
|
189
|
+
}
|
|
179
190
|
}
|
|
180
191
|
}
|
|
181
192
|
function getCodexTokensPath() {
|
|
@@ -190,7 +201,10 @@ function readStoredCodexTokens() {
|
|
|
190
201
|
if (parsed && typeof parsed === "object" && typeof parsed.accessToken === "string" && typeof parsed.refreshToken === "string") {
|
|
191
202
|
return parsed;
|
|
192
203
|
}
|
|
193
|
-
} catch {
|
|
204
|
+
} catch (err) {
|
|
205
|
+
if (!isMissingFileError(err)) {
|
|
206
|
+
logger$t.warn("Could not read stored Codex tokens:", err);
|
|
207
|
+
}
|
|
194
208
|
}
|
|
195
209
|
return null;
|
|
196
210
|
}
|
|
@@ -205,7 +219,10 @@ function writeStoredCodexTokens(tokens) {
|
|
|
205
219
|
function clearStoredCodexTokens() {
|
|
206
220
|
try {
|
|
207
221
|
fs.unlinkSync(getCodexTokensPath());
|
|
208
|
-
} catch {
|
|
222
|
+
} catch (err) {
|
|
223
|
+
if (!isMissingFileError(err)) {
|
|
224
|
+
logger$t.warn("Could not delete Codex token file:", err);
|
|
225
|
+
}
|
|
209
226
|
}
|
|
210
227
|
}
|
|
211
228
|
function mergeChatProviderSecret(provider) {
|
|
@@ -494,6 +511,15 @@ function loadTrustedAppURL(wc, url) {
|
|
|
494
511
|
}
|
|
495
512
|
return wc.loadURL(parsed.toString());
|
|
496
513
|
}
|
|
514
|
+
const urlSafety = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
515
|
+
__proto__: null,
|
|
516
|
+
assertPermittedNavigationURL,
|
|
517
|
+
assertSafeURL,
|
|
518
|
+
isSafeNavigationURL,
|
|
519
|
+
loadInternalDataURL,
|
|
520
|
+
loadPermittedNavigationURL,
|
|
521
|
+
loadTrustedAppURL
|
|
522
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
497
523
|
const MAX_CUSTOM_HISTORY = 50;
|
|
498
524
|
const READER_MODE_DATA_URL_PREFIX = "data:text/html;charset=utf-8,";
|
|
499
525
|
const logger$s = createLogger("Tab");
|
|
@@ -2915,13 +2941,8 @@ function destroySession(tabId) {
|
|
|
2915
2941
|
}
|
|
2916
2942
|
}
|
|
2917
2943
|
const logger$q = createLogger("TabManager");
|
|
2918
|
-
function
|
|
2944
|
+
function sanitizeFilename(title, ext) {
|
|
2919
2945
|
const clean = title.replace(/[<>:"/\\|?*\x00-\x1f]/g, " ").replace(/\s+/g, " ").trim();
|
|
2920
|
-
const base = (clean || "Vessel Page").replace(/\.pdf$/i, "");
|
|
2921
|
-
return `${base}.pdf`;
|
|
2922
|
-
}
|
|
2923
|
-
function sanitizePageFilename(title, ext) {
|
|
2924
|
-
const clean = title.replace(/[<>:\"/\\|?*\x00-\x1f]/g, " ").replace(/\s+/g, " ").trim();
|
|
2925
2946
|
const escapedExt = ext.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2926
2947
|
const regex = new RegExp(`\\.${escapedExt}$`, "i");
|
|
2927
2948
|
const base = (clean || "Vessel Page").replace(regex, "");
|
|
@@ -3150,7 +3171,7 @@ class TabManager {
|
|
|
3150
3171
|
if (!tab) return null;
|
|
3151
3172
|
const { canceled, filePath: filePath2 } = await electron.dialog.showSaveDialog({
|
|
3152
3173
|
title: "Save Page as PDF",
|
|
3153
|
-
defaultPath:
|
|
3174
|
+
defaultPath: sanitizeFilename(tab.state.title || "Vessel Page", "pdf"),
|
|
3154
3175
|
filters: [{ name: "PDF", extensions: ["pdf"] }]
|
|
3155
3176
|
});
|
|
3156
3177
|
if (canceled || !filePath2) return null;
|
|
@@ -3166,7 +3187,7 @@ class TabManager {
|
|
|
3166
3187
|
const ext = format === "MHTML" ? "mhtml" : "html";
|
|
3167
3188
|
const { canceled, filePath: filePath2 } = await electron.dialog.showSaveDialog({
|
|
3168
3189
|
title: "Save Page As",
|
|
3169
|
-
defaultPath:
|
|
3190
|
+
defaultPath: sanitizeFilename(
|
|
3170
3191
|
tab.state.title || "Vessel Page",
|
|
3171
3192
|
ext
|
|
3172
3193
|
),
|
|
@@ -5321,7 +5342,7 @@ function getOfferPrice(offers) {
|
|
|
5321
5342
|
const offer = asStructuredObject(offers);
|
|
5322
5343
|
return firstStructuredString(offer?.price);
|
|
5323
5344
|
}
|
|
5324
|
-
function extractPrimaryEntity(pageType, structuredData,
|
|
5345
|
+
function extractPrimaryEntity(pageType, structuredData, _metaTags) {
|
|
5325
5346
|
if (pageType === "product") {
|
|
5326
5347
|
const product = structuredData?.find(
|
|
5327
5348
|
(e) => e.types.some((t) => /^product$/i.test(t))
|
|
@@ -6406,7 +6427,7 @@ async function extractContentInner(webContents) {
|
|
|
6406
6427
|
webContents
|
|
6407
6428
|
);
|
|
6408
6429
|
}
|
|
6409
|
-
async function extractContent(webContents) {
|
|
6430
|
+
async function extractContent$1(webContents) {
|
|
6410
6431
|
const cacheKey = `${webContents.id}:${webContents.getURL() || ""}`;
|
|
6411
6432
|
const cached = extractionCache.get(cacheKey);
|
|
6412
6433
|
if (cached) {
|
|
@@ -6624,7 +6645,7 @@ async function capturePageSnapshot(url, wc, sendToRendererViews) {
|
|
|
6624
6645
|
if (!shouldTrackSnapshotUrl(url)) return;
|
|
6625
6646
|
const key2 = normalizeUrl(url);
|
|
6626
6647
|
const oldSnap = getSnapshot(key2);
|
|
6627
|
-
const content = await extractContent(wc);
|
|
6648
|
+
const content = await extractContent$1(wc);
|
|
6628
6649
|
const textContent = content.content || "";
|
|
6629
6650
|
const title = content.title || "";
|
|
6630
6651
|
const headings = content.headings || [];
|
|
@@ -6699,6 +6720,60 @@ function schedulePageSnapshotCapture(wc, sendToRendererViews, delayMs = 0, optio
|
|
|
6699
6720
|
}
|
|
6700
6721
|
scheduleTimerAt(wc, sendToRendererViews, nextDueAt, options);
|
|
6701
6722
|
}
|
|
6723
|
+
const trustedIpcSenderIds = /* @__PURE__ */ new Set();
|
|
6724
|
+
function registerTrustedIpcSender(wc) {
|
|
6725
|
+
trustedIpcSenderIds.add(wc.id);
|
|
6726
|
+
wc.once("destroyed", () => trustedIpcSenderIds.delete(wc.id));
|
|
6727
|
+
}
|
|
6728
|
+
function assertTrustedIpcSender(event) {
|
|
6729
|
+
if (!trustedIpcSenderIds.has(event.sender.id)) {
|
|
6730
|
+
throw new Error("Blocked IPC from untrusted renderer");
|
|
6731
|
+
}
|
|
6732
|
+
}
|
|
6733
|
+
function isManagedTabIpcSender(event, tabManager) {
|
|
6734
|
+
return Boolean(tabManager.findTabByWebContentsId(event.sender.id));
|
|
6735
|
+
}
|
|
6736
|
+
function parseIpc(schema, value, label) {
|
|
6737
|
+
const result = schema.safeParse(value);
|
|
6738
|
+
if (!result.success) {
|
|
6739
|
+
const message = result.error.issues.map((i) => i.message).join("; ");
|
|
6740
|
+
throw new Error(
|
|
6741
|
+
label ? `Invalid ${label}: ${message}` : `Invalid input: ${message}`
|
|
6742
|
+
);
|
|
6743
|
+
}
|
|
6744
|
+
return result.data;
|
|
6745
|
+
}
|
|
6746
|
+
function assertString(value, name) {
|
|
6747
|
+
if (typeof value !== "string") throw new Error(`${name} must be a string`);
|
|
6748
|
+
}
|
|
6749
|
+
function assertOptionalString(value, name) {
|
|
6750
|
+
if (value !== void 0 && typeof value !== "string") {
|
|
6751
|
+
throw new Error(`${name} must be a string`);
|
|
6752
|
+
}
|
|
6753
|
+
}
|
|
6754
|
+
function assertNumber(value, name) {
|
|
6755
|
+
if (typeof value !== "number" || Number.isNaN(value)) {
|
|
6756
|
+
throw new Error(`${name} must be a number`);
|
|
6757
|
+
}
|
|
6758
|
+
}
|
|
6759
|
+
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
6760
|
+
function isValidEmail$1(value) {
|
|
6761
|
+
return EMAIL_RE.test(value.trim());
|
|
6762
|
+
}
|
|
6763
|
+
function getActiveTabInfo(tabManager) {
|
|
6764
|
+
const tab = tabManager.getActiveTab();
|
|
6765
|
+
if (!tab) return null;
|
|
6766
|
+
const wc = tab.view.webContents;
|
|
6767
|
+
if (wc.isDestroyed()) return null;
|
|
6768
|
+
return { tab, wc };
|
|
6769
|
+
}
|
|
6770
|
+
function sendSafe(wc, channel, ...args) {
|
|
6771
|
+
if (!wc || wc.isDestroyed()) return;
|
|
6772
|
+
try {
|
|
6773
|
+
wc.send(channel, ...args);
|
|
6774
|
+
} catch {
|
|
6775
|
+
}
|
|
6776
|
+
}
|
|
6702
6777
|
function setSidebarPanelMode(state2, mode, reason = "user") {
|
|
6703
6778
|
state2.uiState.sidebarPanelMode = mode;
|
|
6704
6779
|
if (reason === "user") {
|
|
@@ -6741,15 +6816,8 @@ function getSidebarPanelState(state2) {
|
|
|
6741
6816
|
}
|
|
6742
6817
|
function emitSidebarPanelState(state2) {
|
|
6743
6818
|
const panelState = getSidebarPanelState(state2);
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
}
|
|
6747
|
-
if (!state2.sidebarView.webContents.isDestroyed()) {
|
|
6748
|
-
state2.sidebarView.webContents.send(
|
|
6749
|
-
Channels.SIDEBAR_STATE_UPDATE,
|
|
6750
|
-
panelState
|
|
6751
|
-
);
|
|
6752
|
-
}
|
|
6819
|
+
sendSafe(state2.chromeView.webContents, Channels.SIDEBAR_STATE_UPDATE, panelState);
|
|
6820
|
+
sendSafe(state2.sidebarView.webContents, Channels.SIDEBAR_STATE_UPDATE, panelState);
|
|
6753
6821
|
return panelState;
|
|
6754
6822
|
}
|
|
6755
6823
|
function isSidebarAttached(state2) {
|
|
@@ -7059,8 +7127,8 @@ function createMainWindow(onTabStateChange) {
|
|
|
7059
7127
|
};
|
|
7060
7128
|
const tabManager = new TabManager(mainWindow, onTabStateChange);
|
|
7061
7129
|
const sendToRendererViews = (channel, ...args) => {
|
|
7062
|
-
chromeView.webContents
|
|
7063
|
-
sidebarView.webContents
|
|
7130
|
+
sendSafe(chromeView.webContents, channel, ...args);
|
|
7131
|
+
sendSafe(sidebarView.webContents, channel, ...args);
|
|
7064
7132
|
};
|
|
7065
7133
|
tabManager.onPageLoad((url, wc) => {
|
|
7066
7134
|
const activeWc = tabManager.getActiveTab()?.view.webContents;
|
|
@@ -9681,60 +9749,6 @@ function createProvider(config) {
|
|
|
9681
9749
|
}
|
|
9682
9750
|
return new OpenAICompatProvider(normalized);
|
|
9683
9751
|
}
|
|
9684
|
-
const trustedIpcSenderIds = /* @__PURE__ */ new Set();
|
|
9685
|
-
function registerTrustedIpcSender(wc) {
|
|
9686
|
-
trustedIpcSenderIds.add(wc.id);
|
|
9687
|
-
wc.once("destroyed", () => trustedIpcSenderIds.delete(wc.id));
|
|
9688
|
-
}
|
|
9689
|
-
function assertTrustedIpcSender(event) {
|
|
9690
|
-
if (!trustedIpcSenderIds.has(event.sender.id)) {
|
|
9691
|
-
throw new Error("Blocked IPC from untrusted renderer");
|
|
9692
|
-
}
|
|
9693
|
-
}
|
|
9694
|
-
function isManagedTabIpcSender(event, tabManager) {
|
|
9695
|
-
return Boolean(tabManager.findTabByWebContentsId(event.sender.id));
|
|
9696
|
-
}
|
|
9697
|
-
function parseIpc(schema, value, label) {
|
|
9698
|
-
const result = schema.safeParse(value);
|
|
9699
|
-
if (!result.success) {
|
|
9700
|
-
const message = result.error.issues.map((i) => i.message).join("; ");
|
|
9701
|
-
throw new Error(
|
|
9702
|
-
label ? `Invalid ${label}: ${message}` : `Invalid input: ${message}`
|
|
9703
|
-
);
|
|
9704
|
-
}
|
|
9705
|
-
return result.data;
|
|
9706
|
-
}
|
|
9707
|
-
function assertString(value, name) {
|
|
9708
|
-
if (typeof value !== "string") throw new Error(`${name} must be a string`);
|
|
9709
|
-
}
|
|
9710
|
-
function assertOptionalString(value, name) {
|
|
9711
|
-
if (value !== void 0 && typeof value !== "string") {
|
|
9712
|
-
throw new Error(`${name} must be a string`);
|
|
9713
|
-
}
|
|
9714
|
-
}
|
|
9715
|
-
function assertNumber(value, name) {
|
|
9716
|
-
if (typeof value !== "number" || Number.isNaN(value)) {
|
|
9717
|
-
throw new Error(`${name} must be a number`);
|
|
9718
|
-
}
|
|
9719
|
-
}
|
|
9720
|
-
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
9721
|
-
function isValidEmail$1(value) {
|
|
9722
|
-
return EMAIL_RE.test(value.trim());
|
|
9723
|
-
}
|
|
9724
|
-
function getActiveTabInfo(tabManager) {
|
|
9725
|
-
const tab = tabManager.getActiveTab();
|
|
9726
|
-
if (!tab) return null;
|
|
9727
|
-
const wc = tab.view.webContents;
|
|
9728
|
-
if (wc.isDestroyed()) return null;
|
|
9729
|
-
return { tab, wc };
|
|
9730
|
-
}
|
|
9731
|
-
function sendSafe(wc, channel, ...args) {
|
|
9732
|
-
if (!wc || wc.isDestroyed()) return;
|
|
9733
|
-
try {
|
|
9734
|
-
wc.send(channel, ...args);
|
|
9735
|
-
} catch {
|
|
9736
|
-
}
|
|
9737
|
-
}
|
|
9738
9752
|
function buildSubAgentSystemPrompt(thread) {
|
|
9739
9753
|
const domainBlock = thread.blockedDomains.length > 0 ? `
|
|
9740
9754
|
BLOCKED DOMAINS (never visit): ${thread.blockedDomains.join(", ")}` : "";
|
|
@@ -11740,7 +11754,7 @@ async function resolveSelector(wc, index, selector) {
|
|
|
11740
11754
|
if (typeof fallbackSelector === "string" && fallbackSelector) {
|
|
11741
11755
|
return fallbackSelector;
|
|
11742
11756
|
}
|
|
11743
|
-
const page = await extractContent(wc);
|
|
11757
|
+
const page = await extractContent$1(wc);
|
|
11744
11758
|
const extractedSelector = findSelectorByIndex(page, index);
|
|
11745
11759
|
if (extractedSelector) return extractedSelector;
|
|
11746
11760
|
return null;
|
|
@@ -14318,6 +14332,312 @@ function cartOrigin(url) {
|
|
|
14318
14332
|
return null;
|
|
14319
14333
|
}
|
|
14320
14334
|
}
|
|
14335
|
+
class TabMutex {
|
|
14336
|
+
queue = Promise.resolve();
|
|
14337
|
+
enqueue(fn) {
|
|
14338
|
+
const run = this.queue.then(fn, fn);
|
|
14339
|
+
this.queue = run.then(
|
|
14340
|
+
() => void 0,
|
|
14341
|
+
() => void 0
|
|
14342
|
+
);
|
|
14343
|
+
return run;
|
|
14344
|
+
}
|
|
14345
|
+
}
|
|
14346
|
+
const logger$j = createLogger("PageActions");
|
|
14347
|
+
const DEFAULT_PAGE_SCRIPT_TIMEOUT_MS = 1500;
|
|
14348
|
+
const PAGE_SCRIPT_TIMEOUT = /* @__PURE__ */ Symbol("page-script-timeout");
|
|
14349
|
+
function pageBusyError(action) {
|
|
14350
|
+
return `Error: Page is still busy; ${action} timed out waiting for page scripts. Retry in a moment.`;
|
|
14351
|
+
}
|
|
14352
|
+
async function loadPermittedUrl(wc, url) {
|
|
14353
|
+
const { assertPermittedNavigationURL: assertPermittedNavigationURL2 } = await Promise.resolve().then(() => urlSafety);
|
|
14354
|
+
assertPermittedNavigationURL2(url);
|
|
14355
|
+
await wc.loadURL(url);
|
|
14356
|
+
}
|
|
14357
|
+
async function executePageScript(wc, script, options) {
|
|
14358
|
+
if (wc.isDestroyed()) return null;
|
|
14359
|
+
const timeoutMs = Math.max(150, options?.timeoutMs ?? DEFAULT_PAGE_SCRIPT_TIMEOUT_MS);
|
|
14360
|
+
let timer = null;
|
|
14361
|
+
try {
|
|
14362
|
+
const result = await Promise.race([
|
|
14363
|
+
wc.executeJavaScript(script, options?.userGesture ?? false),
|
|
14364
|
+
new Promise((resolve) => {
|
|
14365
|
+
timer = setTimeout(() => resolve(PAGE_SCRIPT_TIMEOUT), timeoutMs);
|
|
14366
|
+
})
|
|
14367
|
+
]);
|
|
14368
|
+
if (result === PAGE_SCRIPT_TIMEOUT) {
|
|
14369
|
+
return PAGE_SCRIPT_TIMEOUT;
|
|
14370
|
+
}
|
|
14371
|
+
return result;
|
|
14372
|
+
} catch (err) {
|
|
14373
|
+
const label = options?.label ? ` (${options.label})` : "";
|
|
14374
|
+
logger$j.warn(`Failed to execute page script${label}:`, err);
|
|
14375
|
+
return null;
|
|
14376
|
+
} finally {
|
|
14377
|
+
if (timer) {
|
|
14378
|
+
clearTimeout(timer);
|
|
14379
|
+
}
|
|
14380
|
+
}
|
|
14381
|
+
}
|
|
14382
|
+
async function waitForJsReady(wc, timeout = 8e3) {
|
|
14383
|
+
const start = Date.now();
|
|
14384
|
+
while (Date.now() - start < timeout) {
|
|
14385
|
+
const ready = await executePageScript(wc, "1", {
|
|
14386
|
+
timeoutMs: 250,
|
|
14387
|
+
userGesture: true,
|
|
14388
|
+
label: "js-ready probe"
|
|
14389
|
+
});
|
|
14390
|
+
if (ready === 1) return;
|
|
14391
|
+
await sleep(250);
|
|
14392
|
+
}
|
|
14393
|
+
}
|
|
14394
|
+
function waitForPotentialNavigation(wc, beforeUrl, timeout = 2500) {
|
|
14395
|
+
return waitForPotentialNavigation$1(wc, beforeUrl, timeout, QUIET_NAVIGATION_WINDOW_MS);
|
|
14396
|
+
}
|
|
14397
|
+
function getGlanceExtractScript() {
|
|
14398
|
+
return `(function() {
|
|
14399
|
+
var vw = window.innerWidth || document.documentElement.clientWidth || 0;
|
|
14400
|
+
var vh = window.innerHeight || document.documentElement.clientHeight || 0;
|
|
14401
|
+
var sy = window.scrollY || window.pageYOffset || 0;
|
|
14402
|
+
|
|
14403
|
+
function inViewport(el) {
|
|
14404
|
+
var r = el.getBoundingClientRect();
|
|
14405
|
+
return r.bottom > 0 && r.top < vh && r.right > 0 && r.left < vw && r.width > 0 && r.height > 0;
|
|
14406
|
+
}
|
|
14407
|
+
|
|
14408
|
+
function label(el) {
|
|
14409
|
+
return (el.getAttribute('aria-label') || el.textContent || '').trim().slice(0, 120);
|
|
14410
|
+
}
|
|
14411
|
+
|
|
14412
|
+
// Headings visible on screen
|
|
14413
|
+
var headings = [];
|
|
14414
|
+
document.querySelectorAll('h1, h2, h3, h4').forEach(function(h) {
|
|
14415
|
+
if (!inViewport(h)) return;
|
|
14416
|
+
var t = (h.textContent || '').trim();
|
|
14417
|
+
if (t && t.length < 200) headings.push(h.tagName.toLowerCase() + ': ' + t);
|
|
14418
|
+
});
|
|
14419
|
+
|
|
14420
|
+
// Links visible on screen (deduplicated by text)
|
|
14421
|
+
var links = [];
|
|
14422
|
+
var seenLinks = {};
|
|
14423
|
+
var idx = 1;
|
|
14424
|
+
document.querySelectorAll('a[href]').forEach(function(a) {
|
|
14425
|
+
if (!inViewport(a)) return;
|
|
14426
|
+
var t = (a.textContent || '').trim().slice(0, 100);
|
|
14427
|
+
if (!t || t.length < 2 || seenLinks[t]) return;
|
|
14428
|
+
seenLinks[t] = true;
|
|
14429
|
+
links.push({ text: t, href: (a.href || '').slice(0, 200), index: idx++ });
|
|
14430
|
+
});
|
|
14431
|
+
|
|
14432
|
+
// Buttons visible on screen
|
|
14433
|
+
var buttons = [];
|
|
14434
|
+
document.querySelectorAll('button, [role="button"], input[type="submit"], input[type="button"]').forEach(function(b) {
|
|
14435
|
+
if (!inViewport(b)) return;
|
|
14436
|
+
var t = label(b);
|
|
14437
|
+
if (!t || t.length < 1) return;
|
|
14438
|
+
buttons.push({ text: t, index: idx++ });
|
|
14439
|
+
});
|
|
14440
|
+
|
|
14441
|
+
// Input fields visible on screen
|
|
14442
|
+
var inputs = [];
|
|
14443
|
+
document.querySelectorAll('input:not([type="hidden"]):not([type="submit"]):not([type="button"]), select, textarea').forEach(function(inp) {
|
|
14444
|
+
if (!inViewport(inp)) return;
|
|
14445
|
+
var type = (inp.type || inp.tagName.toLowerCase() || '').toLowerCase();
|
|
14446
|
+
var lbl = (inp.getAttribute('aria-label') || inp.getAttribute('placeholder') || inp.name || '').trim();
|
|
14447
|
+
inputs.push({ type: type, label: lbl.slice(0, 80), placeholder: (inp.getAttribute('placeholder') || '').slice(0, 80), index: idx++ });
|
|
14448
|
+
});
|
|
14449
|
+
|
|
14450
|
+
// Content snapshot from main content area using textContent (instant, no reflow)
|
|
14451
|
+
var roots = ['main', 'article', '[role="main"]', '#content', '.content', '.story-body'];
|
|
14452
|
+
var contentRoot = null;
|
|
14453
|
+
for (var i = 0; i < roots.length; i++) {
|
|
14454
|
+
contentRoot = document.querySelector(roots[i]);
|
|
14455
|
+
if (contentRoot && contentRoot.textContent.trim().length > 50) break;
|
|
14456
|
+
contentRoot = null;
|
|
14457
|
+
}
|
|
14458
|
+
var snippet = '';
|
|
14459
|
+
if (contentRoot) {
|
|
14460
|
+
snippet = contentRoot.textContent.replace(/[ \\t]+/g, ' ').replace(/(\\n\\s*){3,}/g, '\\n\\n').trim().slice(0, 8000);
|
|
14461
|
+
} else {
|
|
14462
|
+
// Fallback: grab text from visible elements only
|
|
14463
|
+
var parts = [];
|
|
14464
|
+
document.querySelectorAll('h1, h2, h3, p, li, td, span, div').forEach(function(el) {
|
|
14465
|
+
if (parts.length > 100 || !inViewport(el)) return;
|
|
14466
|
+
var t = (el.textContent || '').trim();
|
|
14467
|
+
if (t.length > 10 && t.length < 500) parts.push(t);
|
|
14468
|
+
});
|
|
14469
|
+
snippet = parts.join('\\n').slice(0, 8000);
|
|
14470
|
+
}
|
|
14471
|
+
|
|
14472
|
+
return {
|
|
14473
|
+
title: document.title || '',
|
|
14474
|
+
url: location.href,
|
|
14475
|
+
headings: headings.slice(0, 20),
|
|
14476
|
+
links: links.slice(0, 40),
|
|
14477
|
+
buttons: buttons.slice(0, 20),
|
|
14478
|
+
inputs: inputs.slice(0, 15),
|
|
14479
|
+
contentSnippet: snippet,
|
|
14480
|
+
viewportHeight: vh,
|
|
14481
|
+
viewportWidth: vw,
|
|
14482
|
+
scrollY: Math.round(sy),
|
|
14483
|
+
};
|
|
14484
|
+
})()`;
|
|
14485
|
+
}
|
|
14486
|
+
async function glanceExtract(wc) {
|
|
14487
|
+
const startMs = Date.now();
|
|
14488
|
+
const result = await executePageScript(wc, getGlanceExtractScript(), { timeoutMs: 2500, label: "glance-extract" });
|
|
14489
|
+
const elapsed = Date.now() - startMs;
|
|
14490
|
+
if (!result || result === PAGE_SCRIPT_TIMEOUT) {
|
|
14491
|
+
return [
|
|
14492
|
+
`# ${wc.getTitle() || "(untitled)"}`,
|
|
14493
|
+
`URL: ${wc.getURL()}`,
|
|
14494
|
+
"",
|
|
14495
|
+
"[read_page mode=glance — page JS thread is completely blocked, no content available]",
|
|
14496
|
+
"[Try: click or type_text to interact directly, or wait a few seconds and retry]"
|
|
14497
|
+
].join("\n");
|
|
14498
|
+
}
|
|
14499
|
+
const sections = [
|
|
14500
|
+
`# ${result.title}`,
|
|
14501
|
+
`URL: ${result.url}`,
|
|
14502
|
+
`Viewport: ${result.viewportWidth}×${result.viewportHeight} scrollY=${result.scrollY}`,
|
|
14503
|
+
`[read_page mode=glance — ${elapsed}ms, showing what's visible on screen]`
|
|
14504
|
+
];
|
|
14505
|
+
if (result.headings.length > 0) {
|
|
14506
|
+
sections.push("", "## Headings", ...result.headings);
|
|
14507
|
+
}
|
|
14508
|
+
if (result.inputs.length > 0) {
|
|
14509
|
+
sections.push("", "## Input Fields");
|
|
14510
|
+
for (const inp of result.inputs) {
|
|
14511
|
+
const desc = inp.label || inp.placeholder || inp.type;
|
|
14512
|
+
sections.push(` [#${inp.index}] ${inp.type}: ${desc}`);
|
|
14513
|
+
}
|
|
14514
|
+
}
|
|
14515
|
+
if (result.buttons.length > 0) {
|
|
14516
|
+
sections.push("", "## Buttons");
|
|
14517
|
+
for (const btn of result.buttons) {
|
|
14518
|
+
sections.push(` [#${btn.index}] ${btn.text}`);
|
|
14519
|
+
}
|
|
14520
|
+
}
|
|
14521
|
+
if (result.links.length > 0) {
|
|
14522
|
+
sections.push("", "## Visible Links");
|
|
14523
|
+
for (const link of result.links) {
|
|
14524
|
+
sections.push(` [#${link.index}] ${link.text}`);
|
|
14525
|
+
}
|
|
14526
|
+
}
|
|
14527
|
+
if (result.contentSnippet) {
|
|
14528
|
+
const truncated = result.contentSnippet.length > 6e3 ? result.contentSnippet.slice(0, 6e3) + "\n[truncated]" : result.contentSnippet;
|
|
14529
|
+
sections.push("", "## Page Content (viewport)", "", truncated);
|
|
14530
|
+
}
|
|
14531
|
+
return sections.join("\n");
|
|
14532
|
+
}
|
|
14533
|
+
function normalizeReadPageMode(mode, pageContent) {
|
|
14534
|
+
if (typeof mode === "string") {
|
|
14535
|
+
const normalized = mode.trim().toLowerCase();
|
|
14536
|
+
if (normalized === "debug") return "debug";
|
|
14537
|
+
if (normalized === "glance") return "glance";
|
|
14538
|
+
if (normalized === "full" || normalized === "summary" || normalized === "interactives_only" || normalized === "forms_only" || normalized === "text_only" || normalized === "visible_only" || normalized === "results_only") {
|
|
14539
|
+
return normalized;
|
|
14540
|
+
}
|
|
14541
|
+
}
|
|
14542
|
+
return pageContent ? chooseAgentReadMode(pageContent) : "visible_only";
|
|
14543
|
+
}
|
|
14544
|
+
async function getPostNavSummary(wc) {
|
|
14545
|
+
const title = wc.getTitle();
|
|
14546
|
+
const titleLine = title ? `
|
|
14547
|
+
Page title: ${title}` : "";
|
|
14548
|
+
const overlaySignal = await executePageScript(
|
|
14549
|
+
wc,
|
|
14550
|
+
`(function() {
|
|
14551
|
+
var signals = [];
|
|
14552
|
+
var bodyStyle = window.getComputedStyle(document.body);
|
|
14553
|
+
var htmlStyle = window.getComputedStyle(document.documentElement);
|
|
14554
|
+
if (bodyStyle.overflow === 'hidden' || htmlStyle.overflow === 'hidden') {
|
|
14555
|
+
signals.push('body-scroll-locked');
|
|
14556
|
+
}
|
|
14557
|
+
var consentSelectors = [
|
|
14558
|
+
'#onetrust-consent-sdk', '#CybotCookiebotDialog', '[class*="consent-banner"]',
|
|
14559
|
+
'[class*="cookie-banner"]', '[class*="privacy-banner"]', '[id*="consent"]',
|
|
14560
|
+
'[class*="gdpr"]', '[data-testid*="consent"]', '[data-testid*="cookie"]',
|
|
14561
|
+
'.fc-consent-root', '#sp_message_container_', '[id*="trustarc"]',
|
|
14562
|
+
'[class*="cmp-"]', '[id*="cmp-"]'
|
|
14563
|
+
];
|
|
14564
|
+
for (var i = 0; i < consentSelectors.length; i++) {
|
|
14565
|
+
try {
|
|
14566
|
+
var el = document.querySelector(consentSelectors[i]);
|
|
14567
|
+
if (el && el.offsetHeight > 50) {
|
|
14568
|
+
signals.push('consent-banner:' + consentSelectors[i]);
|
|
14569
|
+
break;
|
|
14570
|
+
}
|
|
14571
|
+
} catch(e) {}
|
|
14572
|
+
}
|
|
14573
|
+
var vw = window.innerWidth || 0;
|
|
14574
|
+
var vh = window.innerHeight || 0;
|
|
14575
|
+
var vpArea = Math.max(1, vw * vh);
|
|
14576
|
+
var els = document.querySelectorAll('dialog[open], [role="dialog"], [aria-modal="true"]');
|
|
14577
|
+
if (els.length > 0) signals.push('dialog-open');
|
|
14578
|
+
if (signals.length === 0) {
|
|
14579
|
+
var fixed = document.querySelectorAll('div[style*="position: fixed"], div[style*="position:fixed"]');
|
|
14580
|
+
for (var j = 0; j < fixed.length && j < 20; j++) {
|
|
14581
|
+
var r = fixed[j].getBoundingClientRect();
|
|
14582
|
+
if ((r.width * r.height) / vpArea > 0.3) {
|
|
14583
|
+
signals.push('large-fixed-overlay');
|
|
14584
|
+
break;
|
|
14585
|
+
}
|
|
14586
|
+
}
|
|
14587
|
+
}
|
|
14588
|
+
return signals.length > 0 ? signals.join(', ') : null;
|
|
14589
|
+
})()`,
|
|
14590
|
+
{ timeoutMs: 1500, label: "overlay-probe" }
|
|
14591
|
+
);
|
|
14592
|
+
if (overlaySignal && overlaySignal !== PAGE_SCRIPT_TIMEOUT) {
|
|
14593
|
+
return `${titleLine}
|
|
14594
|
+
WARNING: Blocking overlay detected (${overlaySignal}). Call clear_overlays or accept_cookies before reading the page.`;
|
|
14595
|
+
}
|
|
14596
|
+
return titleLine;
|
|
14597
|
+
}
|
|
14598
|
+
async function getPostSearchSummary(wc) {
|
|
14599
|
+
await waitForLoad(wc, 2e3);
|
|
14600
|
+
try {
|
|
14601
|
+
const content = await Promise.race([
|
|
14602
|
+
extractContent$1(wc),
|
|
14603
|
+
new Promise((resolve) => setTimeout(() => resolve(null), 2500))
|
|
14604
|
+
]);
|
|
14605
|
+
if (content && content.content.length > 0) {
|
|
14606
|
+
const scoped = buildScopedContext(content, "results_only");
|
|
14607
|
+
const truncated = scoped.length > 2600 ? `${scoped.slice(0, 2600)}
|
|
14608
|
+
[Search results snapshot truncated...]` : scoped;
|
|
14609
|
+
return `
|
|
14610
|
+
Search results snapshot:
|
|
14611
|
+
${truncated}`;
|
|
14612
|
+
}
|
|
14613
|
+
} catch (err) {
|
|
14614
|
+
logger$j.warn("Failed to build post-search summary, falling back to nav summary:", err);
|
|
14615
|
+
}
|
|
14616
|
+
const fallback = await getPostNavSummary(wc);
|
|
14617
|
+
return fallback ? `${fallback}
|
|
14618
|
+
Search results snapshot unavailable. Use read_page(mode="results_only") if needed.` : `
|
|
14619
|
+
Search results snapshot unavailable. Use read_page(mode="results_only") if needed.`;
|
|
14620
|
+
}
|
|
14621
|
+
async function getPostClickNavSummary(wc, toolProfile) {
|
|
14622
|
+
try {
|
|
14623
|
+
const content = await Promise.race([
|
|
14624
|
+
extractContent$1(wc),
|
|
14625
|
+
new Promise((resolve) => setTimeout(() => resolve(null), 3e3))
|
|
14626
|
+
]);
|
|
14627
|
+
if (content && content.content.length > 0) {
|
|
14628
|
+
const scoped = toolProfile === "compact" ? buildCompactScopedContext(content, "visible_only") : buildScopedContext(content, "visible_only");
|
|
14629
|
+
const maxLen = toolProfile === "compact" ? 1800 : 3e3;
|
|
14630
|
+
const truncated = scoped.length > maxLen ? `${scoped.slice(0, maxLen)}
|
|
14631
|
+
[Page snapshot truncated. Use read_page for full details.]` : scoped;
|
|
14632
|
+
return `
|
|
14633
|
+
Page snapshot after navigation:
|
|
14634
|
+
${truncated}`;
|
|
14635
|
+
}
|
|
14636
|
+
} catch (err) {
|
|
14637
|
+
logger$j.warn("Failed to build post-click navigation summary:", err);
|
|
14638
|
+
}
|
|
14639
|
+
return "";
|
|
14640
|
+
}
|
|
14321
14641
|
function resolveBookmarkFolderTarget$1(args) {
|
|
14322
14642
|
const folderId = typeof args.folderId === "string" ? args.folderId.trim() : typeof args.folder_id === "string" ? args.folder_id.trim() : "";
|
|
14323
14643
|
if (folderId) {
|
|
@@ -14706,18 +15026,6 @@ function buildDefaultEngineShortcut(rawQuery) {
|
|
|
14706
15026
|
appliedFilters: []
|
|
14707
15027
|
};
|
|
14708
15028
|
}
|
|
14709
|
-
class TabMutex {
|
|
14710
|
-
queue = Promise.resolve();
|
|
14711
|
-
enqueue(fn) {
|
|
14712
|
-
const run = this.queue.then(fn, fn);
|
|
14713
|
-
this.queue = run.then(
|
|
14714
|
-
() => void 0,
|
|
14715
|
-
() => void 0
|
|
14716
|
-
);
|
|
14717
|
-
return run;
|
|
14718
|
-
}
|
|
14719
|
-
}
|
|
14720
|
-
const logger$j = createLogger("PageActions");
|
|
14721
15029
|
function getBookmarkMetadataFromArgs(args) {
|
|
14722
15030
|
return normalizeBookmarkMetadata({
|
|
14723
15031
|
intent: args.intent ?? args.intent,
|
|
@@ -14726,311 +15034,6 @@ function getBookmarkMetadataFromArgs(args) {
|
|
|
14726
15034
|
agentHints: args.agentHints ?? args.agent_hints
|
|
14727
15035
|
});
|
|
14728
15036
|
}
|
|
14729
|
-
const DEFAULT_PAGE_SCRIPT_TIMEOUT_MS = 1500;
|
|
14730
|
-
const PAGE_SCRIPT_TIMEOUT = /* @__PURE__ */ Symbol("page-script-timeout");
|
|
14731
|
-
async function loadPermittedUrl(wc, url) {
|
|
14732
|
-
assertPermittedNavigationURL(url);
|
|
14733
|
-
await wc.loadURL(url);
|
|
14734
|
-
}
|
|
14735
|
-
function pageBusyError(action) {
|
|
14736
|
-
return `Error: Page is still busy; ${action} timed out waiting for page scripts. Retry in a moment.`;
|
|
14737
|
-
}
|
|
14738
|
-
async function glanceExtract(wc) {
|
|
14739
|
-
const startMs = Date.now();
|
|
14740
|
-
const result = await executePageScript(
|
|
14741
|
-
wc,
|
|
14742
|
-
`(function() {
|
|
14743
|
-
var vw = window.innerWidth || document.documentElement.clientWidth || 0;
|
|
14744
|
-
var vh = window.innerHeight || document.documentElement.clientHeight || 0;
|
|
14745
|
-
var sy = window.scrollY || window.pageYOffset || 0;
|
|
14746
|
-
|
|
14747
|
-
function inViewport(el) {
|
|
14748
|
-
var r = el.getBoundingClientRect();
|
|
14749
|
-
return r.bottom > 0 && r.top < vh && r.right > 0 && r.left < vw && r.width > 0 && r.height > 0;
|
|
14750
|
-
}
|
|
14751
|
-
|
|
14752
|
-
function label(el) {
|
|
14753
|
-
return (el.getAttribute('aria-label') || el.textContent || '').trim().slice(0, 120);
|
|
14754
|
-
}
|
|
14755
|
-
|
|
14756
|
-
// Headings visible on screen
|
|
14757
|
-
var headings = [];
|
|
14758
|
-
document.querySelectorAll('h1, h2, h3, h4').forEach(function(h) {
|
|
14759
|
-
if (!inViewport(h)) return;
|
|
14760
|
-
var t = (h.textContent || '').trim();
|
|
14761
|
-
if (t && t.length < 200) headings.push(h.tagName.toLowerCase() + ': ' + t);
|
|
14762
|
-
});
|
|
14763
|
-
|
|
14764
|
-
// Links visible on screen (deduplicated by text)
|
|
14765
|
-
var links = [];
|
|
14766
|
-
var seenLinks = {};
|
|
14767
|
-
var idx = 1;
|
|
14768
|
-
document.querySelectorAll('a[href]').forEach(function(a) {
|
|
14769
|
-
if (!inViewport(a)) return;
|
|
14770
|
-
var t = (a.textContent || '').trim().slice(0, 100);
|
|
14771
|
-
if (!t || t.length < 2 || seenLinks[t]) return;
|
|
14772
|
-
seenLinks[t] = true;
|
|
14773
|
-
links.push({ text: t, href: (a.href || '').slice(0, 200), index: idx++ });
|
|
14774
|
-
});
|
|
14775
|
-
|
|
14776
|
-
// Buttons visible on screen
|
|
14777
|
-
var buttons = [];
|
|
14778
|
-
document.querySelectorAll('button, [role="button"], input[type="submit"], input[type="button"]').forEach(function(b) {
|
|
14779
|
-
if (!inViewport(b)) return;
|
|
14780
|
-
var t = label(b);
|
|
14781
|
-
if (!t || t.length < 1) return;
|
|
14782
|
-
buttons.push({ text: t, index: idx++ });
|
|
14783
|
-
});
|
|
14784
|
-
|
|
14785
|
-
// Input fields visible on screen
|
|
14786
|
-
var inputs = [];
|
|
14787
|
-
document.querySelectorAll('input:not([type="hidden"]):not([type="submit"]):not([type="button"]), select, textarea').forEach(function(inp) {
|
|
14788
|
-
if (!inViewport(inp)) return;
|
|
14789
|
-
var type = (inp.type || inp.tagName.toLowerCase() || '').toLowerCase();
|
|
14790
|
-
var lbl = (inp.getAttribute('aria-label') || inp.getAttribute('placeholder') || inp.name || '').trim();
|
|
14791
|
-
inputs.push({ type: type, label: lbl.slice(0, 80), placeholder: (inp.getAttribute('placeholder') || '').slice(0, 80), index: idx++ });
|
|
14792
|
-
});
|
|
14793
|
-
|
|
14794
|
-
// Content snapshot from main content area using textContent (instant, no reflow)
|
|
14795
|
-
var roots = ['main', 'article', '[role="main"]', '#content', '.content', '.story-body'];
|
|
14796
|
-
var contentRoot = null;
|
|
14797
|
-
for (var i = 0; i < roots.length; i++) {
|
|
14798
|
-
contentRoot = document.querySelector(roots[i]);
|
|
14799
|
-
if (contentRoot && contentRoot.textContent.trim().length > 50) break;
|
|
14800
|
-
contentRoot = null;
|
|
14801
|
-
}
|
|
14802
|
-
var snippet = '';
|
|
14803
|
-
if (contentRoot) {
|
|
14804
|
-
snippet = contentRoot.textContent.replace(/[ \\t]+/g, ' ').replace(/(\\n\\s*){3,}/g, '\\n\\n').trim().slice(0, 8000);
|
|
14805
|
-
} else {
|
|
14806
|
-
// Fallback: grab text from visible elements only
|
|
14807
|
-
var parts = [];
|
|
14808
|
-
document.querySelectorAll('h1, h2, h3, p, li, td, span, div').forEach(function(el) {
|
|
14809
|
-
if (parts.length > 100 || !inViewport(el)) return;
|
|
14810
|
-
var t = (el.textContent || '').trim();
|
|
14811
|
-
if (t.length > 10 && t.length < 500) parts.push(t);
|
|
14812
|
-
});
|
|
14813
|
-
snippet = parts.join('\\n').slice(0, 8000);
|
|
14814
|
-
}
|
|
14815
|
-
|
|
14816
|
-
return {
|
|
14817
|
-
title: document.title || '',
|
|
14818
|
-
url: location.href,
|
|
14819
|
-
headings: headings.slice(0, 20),
|
|
14820
|
-
links: links.slice(0, 40),
|
|
14821
|
-
buttons: buttons.slice(0, 20),
|
|
14822
|
-
inputs: inputs.slice(0, 15),
|
|
14823
|
-
contentSnippet: snippet,
|
|
14824
|
-
viewportHeight: vh,
|
|
14825
|
-
viewportWidth: vw,
|
|
14826
|
-
scrollY: Math.round(sy),
|
|
14827
|
-
};
|
|
14828
|
-
})()`,
|
|
14829
|
-
{ timeoutMs: 2500, label: "glance-extract" }
|
|
14830
|
-
);
|
|
14831
|
-
const elapsed = Date.now() - startMs;
|
|
14832
|
-
if (!result || result === PAGE_SCRIPT_TIMEOUT) {
|
|
14833
|
-
return [
|
|
14834
|
-
`# ${wc.getTitle() || "(untitled)"}`,
|
|
14835
|
-
`URL: ${wc.getURL()}`,
|
|
14836
|
-
"",
|
|
14837
|
-
"[read_page mode=glance — page JS thread is completely blocked, no content available]",
|
|
14838
|
-
"[Try: click or type_text to interact directly, or wait a few seconds and retry]"
|
|
14839
|
-
].join("\n");
|
|
14840
|
-
}
|
|
14841
|
-
const sections = [
|
|
14842
|
-
`# ${result.title}`,
|
|
14843
|
-
`URL: ${result.url}`,
|
|
14844
|
-
`Viewport: ${result.viewportWidth}×${result.viewportHeight} scrollY=${result.scrollY}`,
|
|
14845
|
-
`[read_page mode=glance — ${elapsed}ms, showing what's visible on screen]`
|
|
14846
|
-
];
|
|
14847
|
-
if (result.headings.length > 0) {
|
|
14848
|
-
sections.push("", "## Headings", ...result.headings);
|
|
14849
|
-
}
|
|
14850
|
-
if (result.inputs.length > 0) {
|
|
14851
|
-
sections.push("", "## Input Fields");
|
|
14852
|
-
for (const inp of result.inputs) {
|
|
14853
|
-
const desc = inp.label || inp.placeholder || inp.type;
|
|
14854
|
-
sections.push(` [#${inp.index}] ${inp.type}: ${desc}`);
|
|
14855
|
-
}
|
|
14856
|
-
}
|
|
14857
|
-
if (result.buttons.length > 0) {
|
|
14858
|
-
sections.push("", "## Buttons");
|
|
14859
|
-
for (const btn of result.buttons) {
|
|
14860
|
-
sections.push(` [#${btn.index}] ${btn.text}`);
|
|
14861
|
-
}
|
|
14862
|
-
}
|
|
14863
|
-
if (result.links.length > 0) {
|
|
14864
|
-
sections.push("", "## Visible Links");
|
|
14865
|
-
for (const link of result.links) {
|
|
14866
|
-
sections.push(` [#${link.index}] ${link.text}`);
|
|
14867
|
-
}
|
|
14868
|
-
}
|
|
14869
|
-
if (result.contentSnippet) {
|
|
14870
|
-
const truncated = result.contentSnippet.length > 6e3 ? result.contentSnippet.slice(0, 6e3) + "\n[truncated]" : result.contentSnippet;
|
|
14871
|
-
sections.push("", "## Page Content (viewport)", "", truncated);
|
|
14872
|
-
}
|
|
14873
|
-
return sections.join("\n");
|
|
14874
|
-
}
|
|
14875
|
-
function normalizeReadPageMode(mode, pageContent) {
|
|
14876
|
-
if (typeof mode === "string") {
|
|
14877
|
-
const normalized = mode.trim().toLowerCase();
|
|
14878
|
-
if (normalized === "debug") return "debug";
|
|
14879
|
-
if (normalized === "glance") return "glance";
|
|
14880
|
-
if (normalized === "full" || normalized === "summary" || normalized === "interactives_only" || normalized === "forms_only" || normalized === "text_only" || normalized === "visible_only" || normalized === "results_only") {
|
|
14881
|
-
return normalized;
|
|
14882
|
-
}
|
|
14883
|
-
}
|
|
14884
|
-
return pageContent ? chooseAgentReadMode(pageContent) : "visible_only";
|
|
14885
|
-
}
|
|
14886
|
-
async function executePageScript(wc, script, options) {
|
|
14887
|
-
if (wc.isDestroyed()) return null;
|
|
14888
|
-
const timeoutMs = Math.max(
|
|
14889
|
-
150,
|
|
14890
|
-
options?.timeoutMs ?? DEFAULT_PAGE_SCRIPT_TIMEOUT_MS
|
|
14891
|
-
);
|
|
14892
|
-
let timer = null;
|
|
14893
|
-
try {
|
|
14894
|
-
const result = await Promise.race([
|
|
14895
|
-
wc.executeJavaScript(script, options?.userGesture ?? false),
|
|
14896
|
-
new Promise((resolve) => {
|
|
14897
|
-
timer = setTimeout(() => resolve(PAGE_SCRIPT_TIMEOUT), timeoutMs);
|
|
14898
|
-
})
|
|
14899
|
-
]);
|
|
14900
|
-
if (result === PAGE_SCRIPT_TIMEOUT) {
|
|
14901
|
-
return PAGE_SCRIPT_TIMEOUT;
|
|
14902
|
-
}
|
|
14903
|
-
return result;
|
|
14904
|
-
} catch (err) {
|
|
14905
|
-
const label = options?.label ? ` (${options.label})` : "";
|
|
14906
|
-
logger$j.warn(`Failed to execute page script${label}:`, err);
|
|
14907
|
-
return null;
|
|
14908
|
-
} finally {
|
|
14909
|
-
if (timer) {
|
|
14910
|
-
clearTimeout(timer);
|
|
14911
|
-
}
|
|
14912
|
-
}
|
|
14913
|
-
}
|
|
14914
|
-
async function waitForJsReady(wc, timeout = 8e3) {
|
|
14915
|
-
const start = Date.now();
|
|
14916
|
-
while (Date.now() - start < timeout) {
|
|
14917
|
-
const ready = await executePageScript(wc, "1", {
|
|
14918
|
-
timeoutMs: 250,
|
|
14919
|
-
userGesture: true,
|
|
14920
|
-
label: "js-ready probe"
|
|
14921
|
-
});
|
|
14922
|
-
if (ready === 1) return;
|
|
14923
|
-
await sleep(250);
|
|
14924
|
-
}
|
|
14925
|
-
}
|
|
14926
|
-
function waitForPotentialNavigation(wc, beforeUrl, timeout = 2500) {
|
|
14927
|
-
return waitForPotentialNavigation$1(
|
|
14928
|
-
wc,
|
|
14929
|
-
beforeUrl,
|
|
14930
|
-
timeout,
|
|
14931
|
-
QUIET_NAVIGATION_WINDOW_MS
|
|
14932
|
-
);
|
|
14933
|
-
}
|
|
14934
|
-
async function getPostNavSummary(wc) {
|
|
14935
|
-
const title = wc.getTitle();
|
|
14936
|
-
const titleLine = title ? `
|
|
14937
|
-
Page title: ${title}` : "";
|
|
14938
|
-
const overlaySignal = await executePageScript(
|
|
14939
|
-
wc,
|
|
14940
|
-
`(function() {
|
|
14941
|
-
var signals = [];
|
|
14942
|
-
// Body scroll lock is a strong overlay signal
|
|
14943
|
-
var bodyStyle = window.getComputedStyle(document.body);
|
|
14944
|
-
var htmlStyle = window.getComputedStyle(document.documentElement);
|
|
14945
|
-
if (bodyStyle.overflow === 'hidden' || htmlStyle.overflow === 'hidden') {
|
|
14946
|
-
signals.push('body-scroll-locked');
|
|
14947
|
-
}
|
|
14948
|
-
// Check for known consent manager containers
|
|
14949
|
-
var consentSelectors = [
|
|
14950
|
-
'#onetrust-consent-sdk', '#CybotCookiebotDialog', '[class*="consent-banner"]',
|
|
14951
|
-
'[class*="cookie-banner"]', '[class*="privacy-banner"]', '[id*="consent"]',
|
|
14952
|
-
'[class*="gdpr"]', '[data-testid*="consent"]', '[data-testid*="cookie"]',
|
|
14953
|
-
'.fc-consent-root', '#sp_message_container_', '[id*="trustarc"]',
|
|
14954
|
-
'[class*="cmp-"]', '[id*="cmp-"]'
|
|
14955
|
-
];
|
|
14956
|
-
for (var i = 0; i < consentSelectors.length; i++) {
|
|
14957
|
-
try {
|
|
14958
|
-
var el = document.querySelector(consentSelectors[i]);
|
|
14959
|
-
if (el && el.offsetHeight > 50) {
|
|
14960
|
-
signals.push('consent-banner:' + consentSelectors[i]);
|
|
14961
|
-
break;
|
|
14962
|
-
}
|
|
14963
|
-
} catch(e) {}
|
|
14964
|
-
}
|
|
14965
|
-
// Check for large fixed/sticky elements covering viewport
|
|
14966
|
-
var vw = window.innerWidth || 0;
|
|
14967
|
-
var vh = window.innerHeight || 0;
|
|
14968
|
-
var vpArea = Math.max(1, vw * vh);
|
|
14969
|
-
var els = document.querySelectorAll('dialog[open], [role="dialog"], [aria-modal="true"]');
|
|
14970
|
-
if (els.length > 0) signals.push('dialog-open');
|
|
14971
|
-
if (signals.length === 0) {
|
|
14972
|
-
var fixed = document.querySelectorAll('div[style*="position: fixed"], div[style*="position:fixed"]');
|
|
14973
|
-
for (var j = 0; j < fixed.length && j < 20; j++) {
|
|
14974
|
-
var r = fixed[j].getBoundingClientRect();
|
|
14975
|
-
if ((r.width * r.height) / vpArea > 0.3) {
|
|
14976
|
-
signals.push('large-fixed-overlay');
|
|
14977
|
-
break;
|
|
14978
|
-
}
|
|
14979
|
-
}
|
|
14980
|
-
}
|
|
14981
|
-
return signals.length > 0 ? signals.join(', ') : null;
|
|
14982
|
-
})()`,
|
|
14983
|
-
{ timeoutMs: 1500, label: "overlay-probe" }
|
|
14984
|
-
);
|
|
14985
|
-
if (overlaySignal && overlaySignal !== PAGE_SCRIPT_TIMEOUT) {
|
|
14986
|
-
return `${titleLine}
|
|
14987
|
-
WARNING: Blocking overlay detected (${overlaySignal}). Call clear_overlays or accept_cookies before reading the page.`;
|
|
14988
|
-
}
|
|
14989
|
-
return titleLine;
|
|
14990
|
-
}
|
|
14991
|
-
async function getPostSearchSummary(wc) {
|
|
14992
|
-
await waitForLoad(wc, 2e3);
|
|
14993
|
-
try {
|
|
14994
|
-
const content = await Promise.race([
|
|
14995
|
-
extractContent(wc),
|
|
14996
|
-
new Promise((resolve) => setTimeout(() => resolve(null), 2500))
|
|
14997
|
-
]);
|
|
14998
|
-
if (content && content.content.length > 0) {
|
|
14999
|
-
const scoped = buildScopedContext(content, "results_only");
|
|
15000
|
-
const truncated = scoped.length > 2600 ? `${scoped.slice(0, 2600)}
|
|
15001
|
-
[Search results snapshot truncated...]` : scoped;
|
|
15002
|
-
return `
|
|
15003
|
-
Search results snapshot:
|
|
15004
|
-
${truncated}`;
|
|
15005
|
-
}
|
|
15006
|
-
} catch (err) {
|
|
15007
|
-
logger$j.warn("Failed to build post-search summary, falling back to nav summary:", err);
|
|
15008
|
-
}
|
|
15009
|
-
const fallback = await getPostNavSummary(wc);
|
|
15010
|
-
return fallback ? `${fallback}
|
|
15011
|
-
Search results snapshot unavailable. Use read_page(mode="results_only") if needed.` : `
|
|
15012
|
-
Search results snapshot unavailable. Use read_page(mode="results_only") if needed.`;
|
|
15013
|
-
}
|
|
15014
|
-
async function getPostClickNavSummary(wc, toolProfile) {
|
|
15015
|
-
try {
|
|
15016
|
-
const content = await Promise.race([
|
|
15017
|
-
extractContent(wc),
|
|
15018
|
-
new Promise((resolve) => setTimeout(() => resolve(null), 3e3))
|
|
15019
|
-
]);
|
|
15020
|
-
if (content && content.content.length > 0) {
|
|
15021
|
-
const scoped = toolProfile === "compact" ? buildCompactScopedContext(content, "visible_only") : buildScopedContext(content, "visible_only");
|
|
15022
|
-
const maxLen = toolProfile === "compact" ? 1800 : 3e3;
|
|
15023
|
-
const truncated = scoped.length > maxLen ? `${scoped.slice(0, maxLen)}
|
|
15024
|
-
[Page snapshot truncated. Use read_page for full details.]` : scoped;
|
|
15025
|
-
return `
|
|
15026
|
-
Page snapshot after navigation:
|
|
15027
|
-
${truncated}`;
|
|
15028
|
-
}
|
|
15029
|
-
} catch (err) {
|
|
15030
|
-
logger$j.warn("Failed to build post-click navigation summary:", err);
|
|
15031
|
-
}
|
|
15032
|
-
return "";
|
|
15033
|
-
}
|
|
15034
15037
|
async function scrollPage(wc, deltaY) {
|
|
15035
15038
|
const getScrollY = async () => {
|
|
15036
15039
|
const scrollY = await executePageScript(
|
|
@@ -19886,7 +19889,7 @@ function parse(raw) {
|
|
|
19886
19889
|
const items = Array.isArray(raw.items) ? raw.items : [];
|
|
19887
19890
|
return { items };
|
|
19888
19891
|
}
|
|
19889
|
-
|
|
19892
|
+
const state$2 = loadJsonFile({ filePath: filePath$1(), fallback: { items: [] }, parse });
|
|
19890
19893
|
const persistence$2 = createDebouncedJsonPersistence({
|
|
19891
19894
|
debounceMs: 250,
|
|
19892
19895
|
filePath: filePath$1(),
|
|
@@ -20188,8 +20191,8 @@ function registerPrivateIpcHandlers(state2) {
|
|
|
20188
20191
|
ipc.handle(Channels.OPEN_PRIVATE_WINDOW, () => {
|
|
20189
20192
|
createPrivateWindow();
|
|
20190
20193
|
});
|
|
20191
|
-
ipc.handle(Channels.OPEN_NEW_WINDOW, () => {
|
|
20192
|
-
const { createSecondaryWindow: createSecondaryWindow2 } =
|
|
20194
|
+
ipc.handle(Channels.OPEN_NEW_WINDOW, async () => {
|
|
20195
|
+
const { createSecondaryWindow: createSecondaryWindow2 } = await Promise.resolve().then(() => window$1);
|
|
20193
20196
|
createSecondaryWindow2();
|
|
20194
20197
|
});
|
|
20195
20198
|
ipc.handle(Channels.WINDOW_MINIMIZE, () => {
|
|
@@ -20254,9 +20257,7 @@ function createPrivateWindow() {
|
|
|
20254
20257
|
const tabManager = new TabManager(
|
|
20255
20258
|
win,
|
|
20256
20259
|
(tabs, activeId) => {
|
|
20257
|
-
|
|
20258
|
-
chromeView.webContents.send(Channels.TAB_STATE_UPDATE, tabs, activeId);
|
|
20259
|
-
}
|
|
20260
|
+
sendSafe(chromeView.webContents, Channels.TAB_STATE_UPDATE, tabs, activeId);
|
|
20260
20261
|
layoutPrivateViews(state2);
|
|
20261
20262
|
},
|
|
20262
20263
|
{ isPrivate: true, sessionPartition: privateSessionPartition }
|
|
@@ -20293,6 +20294,10 @@ function createPrivateWindow() {
|
|
|
20293
20294
|
logger$h.info("Private browsing window opened");
|
|
20294
20295
|
return state2;
|
|
20295
20296
|
}
|
|
20297
|
+
const window$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
20298
|
+
__proto__: null,
|
|
20299
|
+
createPrivateWindow
|
|
20300
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
20296
20301
|
const secondaryWindows = /* @__PURE__ */ new Set();
|
|
20297
20302
|
function layoutSecondaryViews(state2) {
|
|
20298
20303
|
const { window: win, chromeView, tabManager } = state2;
|
|
@@ -20408,8 +20413,8 @@ function registerSecondaryIpcHandlers(state2) {
|
|
|
20408
20413
|
(_e, groupId) => showGroupContextMenu(state2.tabManager, groupId, state2.window)
|
|
20409
20414
|
);
|
|
20410
20415
|
ipc.handle(Channels.OPEN_NEW_WINDOW, () => createSecondaryWindow());
|
|
20411
|
-
ipc.handle(Channels.OPEN_PRIVATE_WINDOW, () => {
|
|
20412
|
-
const { createPrivateWindow: createPrivateWindow2 } =
|
|
20416
|
+
ipc.handle(Channels.OPEN_PRIVATE_WINDOW, async () => {
|
|
20417
|
+
const { createPrivateWindow: createPrivateWindow2 } = await Promise.resolve().then(() => window$2);
|
|
20413
20418
|
createPrivateWindow2();
|
|
20414
20419
|
});
|
|
20415
20420
|
ipc.handle(Channels.IS_PRIVATE_MODE, () => false);
|
|
@@ -20461,9 +20466,7 @@ function createSecondaryWindow() {
|
|
|
20461
20466
|
chromeView.setBackgroundColor("#00000000");
|
|
20462
20467
|
win.contentView.addChildView(chromeView);
|
|
20463
20468
|
const tabManager = new TabManager(win, (tabs, activeId) => {
|
|
20464
|
-
|
|
20465
|
-
chromeView.webContents.send(Channels.TAB_STATE_UPDATE, tabs, activeId);
|
|
20466
|
-
}
|
|
20469
|
+
sendSafe(chromeView.webContents, Channels.TAB_STATE_UPDATE, tabs, activeId);
|
|
20467
20470
|
layoutSecondaryViews(state2);
|
|
20468
20471
|
});
|
|
20469
20472
|
const state2 = { window: win, chromeView, tabManager };
|
|
@@ -20487,12 +20490,16 @@ function createSecondaryWindow() {
|
|
|
20487
20490
|
win.show();
|
|
20488
20491
|
return state2;
|
|
20489
20492
|
}
|
|
20493
|
+
const window$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
20494
|
+
__proto__: null,
|
|
20495
|
+
createSecondaryWindow
|
|
20496
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
20490
20497
|
const TabIdSchema = zod.z.string().min(1);
|
|
20491
20498
|
const GroupIdSchema = zod.z.string().min(1);
|
|
20492
20499
|
const UrlSchema = zod.z.string().min(1);
|
|
20493
20500
|
const ColorSchema = zod.z.string().min(1);
|
|
20494
20501
|
const FindActionSchema = zod.z.enum(["clearSelection", "keepSelection", "activateSelection"]);
|
|
20495
|
-
function registerTabHandlers(windowState,
|
|
20502
|
+
function registerTabHandlers(windowState, _sendToRendererViews) {
|
|
20496
20503
|
const { tabManager, mainWindow } = windowState;
|
|
20497
20504
|
electron.ipcMain.handle(Channels.OPEN_PRIVATE_WINDOW, (event) => {
|
|
20498
20505
|
assertTrustedIpcSender(event);
|
|
@@ -21131,7 +21138,7 @@ async function handleAIQuery(query, provider, activeWebContents, onChunk, onEnd,
|
|
|
21131
21138
|
const isSummarize = lowerQuery.startsWith("summarize") || lowerQuery.startsWith("tldr") || lowerQuery === "summary";
|
|
21132
21139
|
if (provider.streamAgentQuery && tabManager && activeWebContents && runtime2) {
|
|
21133
21140
|
try {
|
|
21134
|
-
const pageContent = await extractContent(activeWebContents);
|
|
21141
|
+
const pageContent = await extractContent$1(activeWebContents);
|
|
21135
21142
|
const pageType = detectPageType(pageContent);
|
|
21136
21143
|
const defaultReadMode = chooseAgentReadMode(pageContent);
|
|
21137
21144
|
if (provider.agentToolProfile === "compact") {
|
|
@@ -21232,7 +21239,7 @@ ${trackerCtx}`;
|
|
|
21232
21239
|
let prompt;
|
|
21233
21240
|
if (activeWebContents) {
|
|
21234
21241
|
try {
|
|
21235
|
-
const pageContent = await extractContent(activeWebContents);
|
|
21242
|
+
const pageContent = await extractContent$1(activeWebContents);
|
|
21236
21243
|
if (isSummarize) {
|
|
21237
21244
|
prompt = buildSummarizePrompt(pageContent);
|
|
21238
21245
|
} else {
|
|
@@ -21492,7 +21499,7 @@ function registerContentHandlers(windowState) {
|
|
|
21492
21499
|
assertTrustedIpcSender(event);
|
|
21493
21500
|
const activeTab = tabManager.getActiveTab();
|
|
21494
21501
|
if (!activeTab) return null;
|
|
21495
|
-
return extractContent(activeTab.view.webContents);
|
|
21502
|
+
return extractContent$1(activeTab.view.webContents);
|
|
21496
21503
|
});
|
|
21497
21504
|
electron.ipcMain.handle(Channels.READER_MODE_TOGGLE, async (event) => {
|
|
21498
21505
|
assertTrustedIpcSender(event);
|
|
@@ -21506,7 +21513,7 @@ function registerContentHandlers(windowState) {
|
|
|
21506
21513
|
}
|
|
21507
21514
|
} else {
|
|
21508
21515
|
const originalUrl = activeTab.state.url;
|
|
21509
|
-
const content = await extractContent(activeTab.view.webContents);
|
|
21516
|
+
const content = await extractContent$1(activeTab.view.webContents);
|
|
21510
21517
|
const html = generateReaderHTML(content);
|
|
21511
21518
|
activeTab.setReaderMode(true, originalUrl);
|
|
21512
21519
|
void loadInternalDataURL(
|
|
@@ -22631,7 +22638,7 @@ function requiresExplicitMcpApproval(name, args) {
|
|
|
22631
22638
|
if (name === "remove_bookmark_folder" && args.delete_contents === true) return true;
|
|
22632
22639
|
return false;
|
|
22633
22640
|
}
|
|
22634
|
-
function getActiveTabSummary(tabManager) {
|
|
22641
|
+
function getActiveTabSummary$1(tabManager) {
|
|
22635
22642
|
const activeTab = tabManager.getActiveTab();
|
|
22636
22643
|
const activeTabId = tabManager.getActiveTabId();
|
|
22637
22644
|
if (!activeTab || !activeTabId) return null;
|
|
@@ -22671,7 +22678,7 @@ async function getPostActionState(tabManager, name) {
|
|
|
22671
22678
|
if (navActions.includes(name)) {
|
|
22672
22679
|
let warning = "";
|
|
22673
22680
|
try {
|
|
22674
|
-
const page = await extractContent(wc);
|
|
22681
|
+
const page = await extractContent$1(wc);
|
|
22675
22682
|
const issue = getRecoverableAccessIssue(page);
|
|
22676
22683
|
if (issue) {
|
|
22677
22684
|
const blockedUrl = wc.getURL();
|
|
@@ -22704,7 +22711,7 @@ async function getPostActionState(tabManager, name) {
|
|
|
22704
22711
|
}
|
|
22705
22712
|
if (tabActions.includes(name)) {
|
|
22706
22713
|
const activeId = tabManager.getActiveTabId();
|
|
22707
|
-
const active = getActiveTabSummary(tabManager);
|
|
22714
|
+
const active = getActiveTabSummary$1(tabManager);
|
|
22708
22715
|
const count = tabManager.getAllStates().length;
|
|
22709
22716
|
return `
|
|
22710
22717
|
[state: activeTab=${activeId}, title=${JSON.stringify(active?.title ?? "")}, url=${active?.url ?? ""}, totalTabs=${count}]`;
|
|
@@ -24148,7 +24155,7 @@ function registerTools(server, tabManager, runtime2) {
|
|
|
24148
24155
|
const wc = activeTab.view.webContents;
|
|
24149
24156
|
pageUrl = wc.getURL();
|
|
24150
24157
|
pageTitle = wc.getTitle();
|
|
24151
|
-
const page = await extractContent(wc);
|
|
24158
|
+
const page = await extractContent$1(wc);
|
|
24152
24159
|
pageType = detectPageType(page);
|
|
24153
24160
|
} catch (err) {
|
|
24154
24161
|
logger$a.warn("Failed to detect page type for tool scoring, falling back to GENERAL:", err);
|
|
@@ -24314,7 +24321,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
24314
24321
|
const tab = tabManager.getActiveTab();
|
|
24315
24322
|
if (!tab) return asNoActiveTabResponse();
|
|
24316
24323
|
try {
|
|
24317
|
-
const pageContent = await extractContent(tab.view.webContents);
|
|
24324
|
+
const pageContent = await extractContent$1(tab.view.webContents);
|
|
24318
24325
|
const effectiveMode = mode || "full";
|
|
24319
24326
|
return asTextResponse(
|
|
24320
24327
|
await buildExtractResponse(
|
|
@@ -24346,7 +24353,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
24346
24353
|
const tab = tabManager.getActiveTab();
|
|
24347
24354
|
if (!tab) return asNoActiveTabResponse();
|
|
24348
24355
|
try {
|
|
24349
|
-
const pageContent = await extractContent(tab.view.webContents);
|
|
24356
|
+
const pageContent = await extractContent$1(tab.view.webContents);
|
|
24350
24357
|
const effectiveMode = mode || "full";
|
|
24351
24358
|
return asTextResponse(
|
|
24352
24359
|
await buildExtractResponse(
|
|
@@ -24480,7 +24487,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
24480
24487
|
const tab = tabManager.getActiveTab();
|
|
24481
24488
|
if (!tab) return asNoActiveTabResponse();
|
|
24482
24489
|
try {
|
|
24483
|
-
const pageContent = await extractContent(tab.view.webContents);
|
|
24490
|
+
const pageContent = await extractContent$1(tab.view.webContents);
|
|
24484
24491
|
const requestedType = typeof type === "string" && type.trim() ? type.trim().toLowerCase() : "";
|
|
24485
24492
|
const entities = (pageContent.structuredData ?? []).filter(
|
|
24486
24493
|
(entity) => requestedType ? entity.types.some(
|
|
@@ -25583,7 +25590,7 @@ ${JSON.stringify(otherHighlights, null, 2)}`
|
|
|
25583
25590
|
"memory_page_capture",
|
|
25584
25591
|
{ title, folder, tags },
|
|
25585
25592
|
async () => {
|
|
25586
|
-
const page = await extractContent(tab.view.webContents);
|
|
25593
|
+
const page = await extractContent$1(tab.view.webContents);
|
|
25587
25594
|
const saved = capturePageToVault({
|
|
25588
25595
|
page,
|
|
25589
25596
|
title,
|
|
@@ -25704,7 +25711,7 @@ ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`
|
|
|
25704
25711
|
const wc = tab.view.webContents;
|
|
25705
25712
|
let page;
|
|
25706
25713
|
try {
|
|
25707
|
-
page = await extractContent(wc);
|
|
25714
|
+
page = await extractContent$1(wc);
|
|
25708
25715
|
} catch (err) {
|
|
25709
25716
|
logger$a.warn("Failed to extract page while generating suggestions:", err);
|
|
25710
25717
|
return asTextResponse(
|
|
@@ -25720,7 +25727,6 @@ ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`
|
|
|
25720
25727
|
suggestions.push(flowCtx);
|
|
25721
25728
|
suggestions.push("");
|
|
25722
25729
|
}
|
|
25723
|
-
page.url.toLowerCase();
|
|
25724
25730
|
const hasPasswordField = page.forms.some(
|
|
25725
25731
|
(f) => f.fields.some((el) => el.inputType === "password")
|
|
25726
25732
|
);
|
|
@@ -27263,7 +27269,7 @@ const BUNDLED_KIT_IDS = /* @__PURE__ */ new Set([
|
|
|
27263
27269
|
"price-scout",
|
|
27264
27270
|
"form-filler"
|
|
27265
27271
|
]);
|
|
27266
|
-
const KIT_ID_UNSAFE_CHAR_PATTERN = /[
|
|
27272
|
+
const KIT_ID_UNSAFE_CHAR_PATTERN = /[/\\\0]/;
|
|
27267
27273
|
function isSafeAutomationKitId(id) {
|
|
27268
27274
|
return id.length > 0 && !KIT_ID_UNSAFE_CHAR_PATTERN.test(id);
|
|
27269
27275
|
}
|
|
@@ -29133,7 +29139,7 @@ function registerAutofillHandlers(windowState) {
|
|
|
29133
29139
|
const activeTab = windowState.tabManager.getActiveTab();
|
|
29134
29140
|
const wc = activeTab?.view.webContents;
|
|
29135
29141
|
if (!wc) throw new Error("No active tab");
|
|
29136
|
-
const content = await extractContent(wc);
|
|
29142
|
+
const content = await extractContent$1(wc);
|
|
29137
29143
|
const elements = content.interactiveElements || [];
|
|
29138
29144
|
const matches = matchFields(elements, profile);
|
|
29139
29145
|
if (matches.length === 0) {
|
|
@@ -30785,25 +30791,12 @@ async function bootstrap() {
|
|
|
30785
30791
|
count = 0;
|
|
30786
30792
|
}
|
|
30787
30793
|
}
|
|
30788
|
-
|
|
30789
|
-
|
|
30790
|
-
|
|
30791
|
-
if (!state2.sidebarView.webContents.isDestroyed()) {
|
|
30792
|
-
state2.sidebarView.webContents.send(Channels.HIGHLIGHT_COUNT_UPDATE, count);
|
|
30793
|
-
}
|
|
30794
|
-
if (!state2.devtoolsPanelView.webContents.isDestroyed()) {
|
|
30795
|
-
state2.devtoolsPanelView.webContents.send(
|
|
30796
|
-
Channels.HIGHLIGHT_COUNT_UPDATE,
|
|
30797
|
-
count
|
|
30798
|
-
);
|
|
30799
|
-
}
|
|
30794
|
+
sendSafe(state2.chromeView.webContents, Channels.HIGHLIGHT_COUNT_UPDATE, count);
|
|
30795
|
+
sendSafe(state2.sidebarView.webContents, Channels.HIGHLIGHT_COUNT_UPDATE, count);
|
|
30796
|
+
sendSafe(state2.devtoolsPanelView.webContents, Channels.HIGHLIGHT_COUNT_UPDATE, count);
|
|
30800
30797
|
};
|
|
30801
30798
|
const windowState = createMainWindow((tabs, activeId, meta) => {
|
|
30802
|
-
windowState.chromeView.webContents.
|
|
30803
|
-
Channels.TAB_STATE_UPDATE,
|
|
30804
|
-
tabs,
|
|
30805
|
-
activeId
|
|
30806
|
-
);
|
|
30799
|
+
sendSafe(windowState.chromeView.webContents, Channels.TAB_STATE_UPDATE, tabs, activeId);
|
|
30807
30800
|
void syncActiveHighlightCount(windowState);
|
|
30808
30801
|
layoutViews(windowState);
|
|
30809
30802
|
if (meta.persistSession) {
|
|
@@ -30826,18 +30819,12 @@ async function bootstrap() {
|
|
|
30826
30819
|
runtime = new AgentRuntime(tabManager);
|
|
30827
30820
|
installAdBlocking(tabManager);
|
|
30828
30821
|
setDevToolsPanelListener((state2) => {
|
|
30829
|
-
|
|
30830
|
-
devtoolsPanelView.webContents.send(Channels.DEVTOOLS_PANEL_STATE, state2);
|
|
30831
|
-
}
|
|
30822
|
+
sendSafe(devtoolsPanelView.webContents, Channels.DEVTOOLS_PANEL_STATE, state2);
|
|
30832
30823
|
});
|
|
30833
30824
|
registerIpcHandlers(windowState, runtime);
|
|
30834
30825
|
tabManager.onSecurityStateChange((tabId, state2) => {
|
|
30835
|
-
|
|
30836
|
-
|
|
30837
|
-
}
|
|
30838
|
-
if (!sidebarView.webContents.isDestroyed()) {
|
|
30839
|
-
sidebarView.webContents.send(Channels.SECURITY_STATE_UPDATE, { tabId, state: state2 });
|
|
30840
|
-
}
|
|
30826
|
+
sendSafe(chromeView.webContents, Channels.SECURITY_STATE_UPDATE, { tabId, state: state2 });
|
|
30827
|
+
sendSafe(sidebarView.webContents, Channels.SECURITY_STATE_UPDATE, { tabId, state: state2 });
|
|
30841
30828
|
});
|
|
30842
30829
|
registerHighlightShortcut(windowState.mainWindow, tabManager);
|
|
30843
30830
|
setupAppMenu({
|
|
@@ -30871,21 +30858,19 @@ async function bootstrap() {
|
|
|
30871
30858
|
}
|
|
30872
30859
|
},
|
|
30873
30860
|
clearBrowsingData: () => {
|
|
30874
|
-
|
|
30875
|
-
chromeView.webContents.send(Channels.CLEAR_BROWSING_DATA_OPEN);
|
|
30876
|
-
}
|
|
30861
|
+
sendSafe(chromeView.webContents, Channels.CLEAR_BROWSING_DATA_OPEN);
|
|
30877
30862
|
},
|
|
30878
30863
|
togglePictureInPicture: () => {
|
|
30879
30864
|
void togglePictureInPicture(tabManager);
|
|
30880
30865
|
}
|
|
30881
30866
|
});
|
|
30882
30867
|
subscribe((state2) => {
|
|
30883
|
-
chromeView.webContents
|
|
30884
|
-
sidebarView.webContents
|
|
30868
|
+
sendSafe(chromeView.webContents, Channels.BOOKMARKS_UPDATE, state2);
|
|
30869
|
+
sendSafe(sidebarView.webContents, Channels.BOOKMARKS_UPDATE, state2);
|
|
30885
30870
|
});
|
|
30886
30871
|
subscribe$1((state2) => {
|
|
30887
|
-
chromeView.webContents
|
|
30888
|
-
sidebarView.webContents
|
|
30872
|
+
sendSafe(chromeView.webContents, Channels.HISTORY_UPDATE, state2);
|
|
30873
|
+
sendSafe(sidebarView.webContents, Channels.HISTORY_UPDATE, state2);
|
|
30889
30874
|
});
|
|
30890
30875
|
installDownloadHandler(chromeView);
|
|
30891
30876
|
installPermissionHandler();
|