@quanta-intellect/vessel-browser 0.1.127 → 0.1.130
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 +672 -665
- package/out/preload/content-script.js +39 -2
- package/out/renderer/assets/{index-DW3ChyZf.js → index-BjtfG1IG.js} +615 -1485
- package/out/renderer/assets/{index-CwDcicSR.css → index-CWy6khUL.css} +778 -158
- package/out/renderer/index.html +2 -2
- package/package.json +10 -1
package/out/main/index.js
CHANGED
|
@@ -94,7 +94,7 @@ const defaults = {
|
|
|
94
94
|
clearBookmarksOnLaunch: false,
|
|
95
95
|
obsidianVaultPath: "",
|
|
96
96
|
approvalMode: "confirm-dangerous",
|
|
97
|
-
agentTranscriptMode: "
|
|
97
|
+
agentTranscriptMode: "off",
|
|
98
98
|
chatProvider: null,
|
|
99
99
|
maxToolIterations: 200,
|
|
100
100
|
domainPolicy: { allowedDomains: [], blockedDomains: [] },
|
|
@@ -114,12 +114,15 @@ const defaults = {
|
|
|
114
114
|
const SAVE_DEBOUNCE_MS$6 = 150;
|
|
115
115
|
const CHAT_PROVIDER_SECRET_FILENAME = "vessel-chat-provider-secret";
|
|
116
116
|
const CODEX_TOKENS_FILENAME = "vessel-codex-tokens";
|
|
117
|
-
const logger$
|
|
117
|
+
const logger$u = createLogger("Settings");
|
|
118
118
|
const SETTABLE_KEYS = new Set(Object.keys(defaults));
|
|
119
119
|
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$u.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$u.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$u.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$u.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$u.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$u.warn("Could not delete Codex token file:", err);
|
|
225
|
+
}
|
|
209
226
|
}
|
|
210
227
|
}
|
|
211
228
|
function mergeChatProviderSecret(provider) {
|
|
@@ -276,6 +293,11 @@ function sanitizeChatProvider(provider) {
|
|
|
276
293
|
reasoningEffort: sanitizeReasoningEffortLevel$1(provider.reasoningEffort)
|
|
277
294
|
} : null;
|
|
278
295
|
}
|
|
296
|
+
function sanitizeAgentTranscriptMode(mode, legacyEnabled) {
|
|
297
|
+
if (mode === "full") return "full";
|
|
298
|
+
if (mode === "off" || mode === "summary") return "off";
|
|
299
|
+
return legacyEnabled === true ? "full" : "off";
|
|
300
|
+
}
|
|
279
301
|
function loadSettings() {
|
|
280
302
|
if (settings) return settings;
|
|
281
303
|
settingsIssues = [];
|
|
@@ -298,7 +320,10 @@ function loadSettings() {
|
|
|
298
320
|
sourceDoNotAllowList: sanitizeStringList(
|
|
299
321
|
parsed.sourceDoNotAllowList ?? defaults.sourceDoNotAllowList
|
|
300
322
|
),
|
|
301
|
-
agentTranscriptMode:
|
|
323
|
+
agentTranscriptMode: sanitizeAgentTranscriptMode(
|
|
324
|
+
parsed.agentTranscriptMode,
|
|
325
|
+
parsed.showAgentTranscript
|
|
326
|
+
)
|
|
302
327
|
};
|
|
303
328
|
} catch (error) {
|
|
304
329
|
if (fs.existsSync(getSettingsPath())) {
|
|
@@ -326,7 +351,7 @@ function persistNow() {
|
|
|
326
351
|
JSON.stringify(buildPersistedSettings(settings), null, 2),
|
|
327
352
|
{ encoding: "utf-8", mode: 384 }
|
|
328
353
|
)
|
|
329
|
-
).then(() => fs.promises.chmod(getSettingsPath(), 384).catch(() => void 0)).catch((err) => logger$
|
|
354
|
+
).then(() => fs.promises.chmod(getSettingsPath(), 384).catch(() => void 0)).catch((err) => logger$u.error("Failed to save settings:", err));
|
|
330
355
|
}
|
|
331
356
|
function saveSettings() {
|
|
332
357
|
saveDirty = true;
|
|
@@ -494,9 +519,18 @@ function loadTrustedAppURL(wc, url) {
|
|
|
494
519
|
}
|
|
495
520
|
return wc.loadURL(parsed.toString());
|
|
496
521
|
}
|
|
522
|
+
const urlSafety = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
523
|
+
__proto__: null,
|
|
524
|
+
assertPermittedNavigationURL,
|
|
525
|
+
assertSafeURL,
|
|
526
|
+
isSafeNavigationURL,
|
|
527
|
+
loadInternalDataURL,
|
|
528
|
+
loadPermittedNavigationURL,
|
|
529
|
+
loadTrustedAppURL
|
|
530
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
497
531
|
const MAX_CUSTOM_HISTORY = 50;
|
|
498
532
|
const READER_MODE_DATA_URL_PREFIX = "data:text/html;charset=utf-8,";
|
|
499
|
-
const logger$
|
|
533
|
+
const logger$t = createLogger("Tab");
|
|
500
534
|
const sessionCertExceptions = /* @__PURE__ */ new WeakMap();
|
|
501
535
|
const sessionsWithVerifyProc = /* @__PURE__ */ new WeakSet();
|
|
502
536
|
const CERT_VERIFY_TRUST = 0;
|
|
@@ -562,7 +596,7 @@ class Tab {
|
|
|
562
596
|
guardedLoadURL(url, options) {
|
|
563
597
|
const blockReason = this.getNavigationBlockReason(url);
|
|
564
598
|
if (blockReason) {
|
|
565
|
-
logger$
|
|
599
|
+
logger$t.warn(blockReason);
|
|
566
600
|
return blockReason;
|
|
567
601
|
}
|
|
568
602
|
void this.view.webContents.loadURL(url, options);
|
|
@@ -646,7 +680,7 @@ class Tab {
|
|
|
646
680
|
wc.setWindowOpenHandler(({ url, disposition }) => {
|
|
647
681
|
const error = this.getNavigationBlockReason(url);
|
|
648
682
|
if (error) {
|
|
649
|
-
logger$
|
|
683
|
+
logger$t.warn(error);
|
|
650
684
|
return { action: "deny" };
|
|
651
685
|
}
|
|
652
686
|
this.onOpenUrl?.({
|
|
@@ -660,7 +694,7 @@ class Tab {
|
|
|
660
694
|
const error = this.getNavigationBlockReason(url);
|
|
661
695
|
if (!error) return;
|
|
662
696
|
event.preventDefault();
|
|
663
|
-
logger$
|
|
697
|
+
logger$t.warn(`${context}: ${error}`);
|
|
664
698
|
};
|
|
665
699
|
wc.on("will-navigate", (event, url) => {
|
|
666
700
|
blockNavigation(event, url, "Blocked top-level navigation");
|
|
@@ -744,7 +778,7 @@ class Tab {
|
|
|
744
778
|
::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.12); border-radius: 999px; }
|
|
745
779
|
::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.22); }
|
|
746
780
|
::-webkit-scrollbar-corner { background: transparent; }
|
|
747
|
-
`).catch((err) => logger$
|
|
781
|
+
`).catch((err) => logger$t.warn("Failed to inject scrollbar CSS:", err));
|
|
748
782
|
});
|
|
749
783
|
wc.on("page-favicon-updated", (_, favicons) => {
|
|
750
784
|
this._state.favicon = favicons[0] || "";
|
|
@@ -780,7 +814,7 @@ class Tab {
|
|
|
780
814
|
).then((highlightedText) => {
|
|
781
815
|
this.buildContextMenu(wc, params, highlightedText.trim());
|
|
782
816
|
}).catch((err) => {
|
|
783
|
-
logger$
|
|
817
|
+
logger$t.warn("Failed to inspect highlighted text for context menu:", err);
|
|
784
818
|
this.buildContextMenu(wc, params, "");
|
|
785
819
|
});
|
|
786
820
|
});
|
|
@@ -981,7 +1015,7 @@ class Tab {
|
|
|
981
1015
|
"document.documentElement.outerHTML"
|
|
982
1016
|
);
|
|
983
1017
|
} catch (err) {
|
|
984
|
-
logger$
|
|
1018
|
+
logger$t.warn("Failed to retrieve page source:", err);
|
|
985
1019
|
return;
|
|
986
1020
|
}
|
|
987
1021
|
const escaped = html.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
@@ -1109,7 +1143,7 @@ class Tab {
|
|
|
1109
1143
|
document.addEventListener('mouseup', window.__vesselHighlightHandler);
|
|
1110
1144
|
}
|
|
1111
1145
|
})()
|
|
1112
|
-
`).catch((err) => logger$
|
|
1146
|
+
`).catch((err) => logger$t.warn("Failed to inject highlight listener:", err));
|
|
1113
1147
|
} else {
|
|
1114
1148
|
void wc.executeJavaScript(`
|
|
1115
1149
|
(function() {
|
|
@@ -1120,7 +1154,7 @@ class Tab {
|
|
|
1120
1154
|
delete window.__vesselHighlightHandler;
|
|
1121
1155
|
}
|
|
1122
1156
|
})()
|
|
1123
|
-
`).catch((err) => logger$
|
|
1157
|
+
`).catch((err) => logger$t.warn("Failed to remove highlight listener:", err));
|
|
1124
1158
|
}
|
|
1125
1159
|
}
|
|
1126
1160
|
get webContentsId() {
|
|
@@ -1157,7 +1191,7 @@ const SEARCH_ENGINE_PRESETS = {
|
|
|
1157
1191
|
ecosia: { label: "Ecosia", url: "https://www.ecosia.org/search?q=" },
|
|
1158
1192
|
kagi: { label: "Kagi", url: "https://kagi.com/search?q=" }
|
|
1159
1193
|
};
|
|
1160
|
-
const logger$
|
|
1194
|
+
const logger$s = createLogger("JsonPersistence");
|
|
1161
1195
|
function canUseSafeStorage() {
|
|
1162
1196
|
try {
|
|
1163
1197
|
return electron.safeStorage.isEncryptionAvailable();
|
|
@@ -1222,7 +1256,7 @@ function createDebouncedJsonPersistence({
|
|
|
1222
1256
|
data,
|
|
1223
1257
|
typeof data === "string" ? { encoding: "utf-8", mode: 384 } : { mode: 384 }
|
|
1224
1258
|
)
|
|
1225
|
-
).then(() => fs.promises.chmod(filePath2, 384).catch(() => void 0)).catch((err) => logger$
|
|
1259
|
+
).then(() => fs.promises.chmod(filePath2, 384).catch(() => void 0)).catch((err) => logger$s.error(`Failed to save ${logLabel}:`, err));
|
|
1226
1260
|
};
|
|
1227
1261
|
const schedule = () => {
|
|
1228
1262
|
saveDirty2 = true;
|
|
@@ -2914,14 +2948,9 @@ function destroySession(tabId) {
|
|
|
2914
2948
|
sessions.delete(tabId);
|
|
2915
2949
|
}
|
|
2916
2950
|
}
|
|
2917
|
-
const logger$
|
|
2918
|
-
function
|
|
2951
|
+
const logger$r = createLogger("TabManager");
|
|
2952
|
+
function sanitizeFilename(title, ext) {
|
|
2919
2953
|
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
2954
|
const escapedExt = ext.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2926
2955
|
const regex = new RegExp(`\\.${escapedExt}$`, "i");
|
|
2927
2956
|
const base = (clean || "Vessel Page").replace(regex, "");
|
|
@@ -3150,7 +3179,7 @@ class TabManager {
|
|
|
3150
3179
|
if (!tab) return null;
|
|
3151
3180
|
const { canceled, filePath: filePath2 } = await electron.dialog.showSaveDialog({
|
|
3152
3181
|
title: "Save Page as PDF",
|
|
3153
|
-
defaultPath:
|
|
3182
|
+
defaultPath: sanitizeFilename(tab.state.title || "Vessel Page", "pdf"),
|
|
3154
3183
|
filters: [{ name: "PDF", extensions: ["pdf"] }]
|
|
3155
3184
|
});
|
|
3156
3185
|
if (canceled || !filePath2) return null;
|
|
@@ -3166,7 +3195,7 @@ class TabManager {
|
|
|
3166
3195
|
const ext = format === "MHTML" ? "mhtml" : "html";
|
|
3167
3196
|
const { canceled, filePath: filePath2 } = await electron.dialog.showSaveDialog({
|
|
3168
3197
|
title: "Save Page As",
|
|
3169
|
-
defaultPath:
|
|
3198
|
+
defaultPath: sanitizeFilename(
|
|
3170
3199
|
tab.state.title || "Vessel Page",
|
|
3171
3200
|
ext
|
|
3172
3201
|
),
|
|
@@ -3314,7 +3343,7 @@ class TabManager {
|
|
|
3314
3343
|
}));
|
|
3315
3344
|
if (entries.length > 0) {
|
|
3316
3345
|
void highlightBatchOnPage(wc, entries).catch(
|
|
3317
|
-
(err) => logger$
|
|
3346
|
+
(err) => logger$r.warn("Failed to batch highlight:", err)
|
|
3318
3347
|
);
|
|
3319
3348
|
}
|
|
3320
3349
|
}
|
|
@@ -3336,12 +3365,12 @@ class TabManager {
|
|
|
3336
3365
|
const result = await captureSelectionHighlight(wc);
|
|
3337
3366
|
if (result.success && result.text) {
|
|
3338
3367
|
await highlightOnPage(wc, null, result.text, void 0, void 0, "yellow").catch(
|
|
3339
|
-
(err) => logger$
|
|
3368
|
+
(err) => logger$r.warn("Failed to capture highlight:", err)
|
|
3340
3369
|
);
|
|
3341
3370
|
}
|
|
3342
3371
|
this.highlightCaptureCallback?.(result);
|
|
3343
3372
|
} catch (err) {
|
|
3344
|
-
logger$
|
|
3373
|
+
logger$r.warn("Failed to capture highlight from page:", err);
|
|
3345
3374
|
this.highlightCaptureCallback?.({
|
|
3346
3375
|
success: false,
|
|
3347
3376
|
message: "Could not capture selection"
|
|
@@ -3366,7 +3395,7 @@ class TabManager {
|
|
|
3366
3395
|
void this.removeHighlightMarksForText(wc, text);
|
|
3367
3396
|
}
|
|
3368
3397
|
} catch (err) {
|
|
3369
|
-
logger$
|
|
3398
|
+
logger$r.warn("Failed to remove highlight from matching tab:", err);
|
|
3370
3399
|
}
|
|
3371
3400
|
}
|
|
3372
3401
|
this.highlightCaptureCallback?.({
|
|
@@ -3397,12 +3426,12 @@ class TabManager {
|
|
|
3397
3426
|
void 0,
|
|
3398
3427
|
color
|
|
3399
3428
|
).catch(
|
|
3400
|
-
(err) => logger$
|
|
3429
|
+
(err) => logger$r.warn("Failed to update highlight color:", err)
|
|
3401
3430
|
);
|
|
3402
3431
|
});
|
|
3403
3432
|
}
|
|
3404
3433
|
} catch (err) {
|
|
3405
|
-
logger$
|
|
3434
|
+
logger$r.warn("Failed to iterate highlights for color change:", err);
|
|
3406
3435
|
}
|
|
3407
3436
|
}
|
|
3408
3437
|
this.highlightCaptureCallback?.({
|
|
@@ -3457,7 +3486,7 @@ class TabManager {
|
|
|
3457
3486
|
});
|
|
3458
3487
|
})()`
|
|
3459
3488
|
).catch(
|
|
3460
|
-
(err) => logger$
|
|
3489
|
+
(err) => logger$r.warn("Failed to remove highlight marks:", err)
|
|
3461
3490
|
);
|
|
3462
3491
|
}
|
|
3463
3492
|
broadcastState(meta = { persistSession: false }) {
|
|
@@ -4661,7 +4690,7 @@ function errorResult(error, value) {
|
|
|
4661
4690
|
function getErrorMessage(error, fallback = "Unknown error") {
|
|
4662
4691
|
return error instanceof Error && error.message ? error.message : fallback;
|
|
4663
4692
|
}
|
|
4664
|
-
const logger$
|
|
4693
|
+
const logger$q = createLogger("Premium");
|
|
4665
4694
|
const VERIFICATION_API = process.env.VESSEL_PREMIUM_API || "https://vesselpremium.quantaintellect.com";
|
|
4666
4695
|
const FREE_TOOL_ITERATION_LIMIT = 50;
|
|
4667
4696
|
const REVALIDATION_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -4837,7 +4866,7 @@ async function verifySubscription$1(identifier) {
|
|
|
4837
4866
|
});
|
|
4838
4867
|
if (!res.ok) {
|
|
4839
4868
|
const detail = await readApiErrorDetail(res);
|
|
4840
|
-
logger$
|
|
4869
|
+
logger$q.warn(
|
|
4841
4870
|
"Verification API returned a non-OK status:",
|
|
4842
4871
|
res.status,
|
|
4843
4872
|
detail
|
|
@@ -4856,7 +4885,7 @@ async function verifySubscription$1(identifier) {
|
|
|
4856
4885
|
setSetting("premium", updated);
|
|
4857
4886
|
return updated;
|
|
4858
4887
|
} catch (err) {
|
|
4859
|
-
logger$
|
|
4888
|
+
logger$q.warn("Verification failed:", err);
|
|
4860
4889
|
return current;
|
|
4861
4890
|
}
|
|
4862
4891
|
}
|
|
@@ -5321,7 +5350,7 @@ function getOfferPrice(offers) {
|
|
|
5321
5350
|
const offer = asStructuredObject(offers);
|
|
5322
5351
|
return firstStructuredString(offer?.price);
|
|
5323
5352
|
}
|
|
5324
|
-
function extractPrimaryEntity(pageType, structuredData,
|
|
5353
|
+
function extractPrimaryEntity(pageType, structuredData, _metaTags) {
|
|
5325
5354
|
if (pageType === "product") {
|
|
5326
5355
|
const product = structuredData?.find(
|
|
5327
5356
|
(e) => e.types.some((t) => /^product$/i.test(t))
|
|
@@ -5511,7 +5540,7 @@ const EXTRACT_TIMEOUT_MAX_MS = 2e4;
|
|
|
5511
5540
|
const MUTATION_CAPTURE_INTERVAL_MS = 5e3;
|
|
5512
5541
|
const MUTATION_SETTLE_AFTER_MS = 1500;
|
|
5513
5542
|
const AGENT_STREAM_IDLE_TIMEOUT_MS = 3e4;
|
|
5514
|
-
const logger$
|
|
5543
|
+
const logger$p = createLogger("Extractor");
|
|
5515
5544
|
const EXTRACTION_CACHE_TTL_MS = 1500;
|
|
5516
5545
|
const MAX_EXTRACTION_CACHE_ENTRIES = 50;
|
|
5517
5546
|
const extractionCache = new BoundedCache(
|
|
@@ -6276,9 +6305,9 @@ async function executeScript(webContents, script, options = {}) {
|
|
|
6276
6305
|
const message = err instanceof Error ? err.message : String(err);
|
|
6277
6306
|
const detail = `Failed to execute page script${label} on ${url}: ${message}`;
|
|
6278
6307
|
if (options.warnOnFailure) {
|
|
6279
|
-
logger$
|
|
6308
|
+
logger$p.warn(detail);
|
|
6280
6309
|
} else {
|
|
6281
|
-
logger$
|
|
6310
|
+
logger$p.debug(detail);
|
|
6282
6311
|
}
|
|
6283
6312
|
return null;
|
|
6284
6313
|
} finally {
|
|
@@ -6387,7 +6416,7 @@ async function estimateExtractionTimeout(webContents) {
|
|
|
6387
6416
|
return EXTRACT_TIMEOUT_BASE_MS + extra;
|
|
6388
6417
|
}
|
|
6389
6418
|
} catch (err) {
|
|
6390
|
-
logger$
|
|
6419
|
+
logger$p.warn("Failed to estimate extraction timeout, using base timeout:", err);
|
|
6391
6420
|
}
|
|
6392
6421
|
return EXTRACT_TIMEOUT_BASE_MS;
|
|
6393
6422
|
}
|
|
@@ -6406,7 +6435,7 @@ async function extractContentInner(webContents) {
|
|
|
6406
6435
|
webContents
|
|
6407
6436
|
);
|
|
6408
6437
|
}
|
|
6409
|
-
async function extractContent(webContents) {
|
|
6438
|
+
async function extractContent$1(webContents) {
|
|
6410
6439
|
const cacheKey = `${webContents.id}:${webContents.getURL() || ""}`;
|
|
6411
6440
|
const cached = extractionCache.get(cacheKey);
|
|
6412
6441
|
if (cached) {
|
|
@@ -6624,7 +6653,7 @@ async function capturePageSnapshot(url, wc, sendToRendererViews) {
|
|
|
6624
6653
|
if (!shouldTrackSnapshotUrl(url)) return;
|
|
6625
6654
|
const key2 = normalizeUrl(url);
|
|
6626
6655
|
const oldSnap = getSnapshot(key2);
|
|
6627
|
-
const content = await extractContent(wc);
|
|
6656
|
+
const content = await extractContent$1(wc);
|
|
6628
6657
|
const textContent = content.content || "";
|
|
6629
6658
|
const title = content.title || "";
|
|
6630
6659
|
const headings = content.headings || [];
|
|
@@ -6699,6 +6728,60 @@ function schedulePageSnapshotCapture(wc, sendToRendererViews, delayMs = 0, optio
|
|
|
6699
6728
|
}
|
|
6700
6729
|
scheduleTimerAt(wc, sendToRendererViews, nextDueAt, options);
|
|
6701
6730
|
}
|
|
6731
|
+
const trustedIpcSenderIds = /* @__PURE__ */ new Set();
|
|
6732
|
+
function registerTrustedIpcSender(wc) {
|
|
6733
|
+
trustedIpcSenderIds.add(wc.id);
|
|
6734
|
+
wc.once("destroyed", () => trustedIpcSenderIds.delete(wc.id));
|
|
6735
|
+
}
|
|
6736
|
+
function assertTrustedIpcSender(event) {
|
|
6737
|
+
if (!trustedIpcSenderIds.has(event.sender.id)) {
|
|
6738
|
+
throw new Error("Blocked IPC from untrusted renderer");
|
|
6739
|
+
}
|
|
6740
|
+
}
|
|
6741
|
+
function isManagedTabIpcSender(event, tabManager) {
|
|
6742
|
+
return Boolean(tabManager.findTabByWebContentsId(event.sender.id));
|
|
6743
|
+
}
|
|
6744
|
+
function parseIpc(schema, value, label) {
|
|
6745
|
+
const result = schema.safeParse(value);
|
|
6746
|
+
if (!result.success) {
|
|
6747
|
+
const message = result.error.issues.map((i) => i.message).join("; ");
|
|
6748
|
+
throw new Error(
|
|
6749
|
+
label ? `Invalid ${label}: ${message}` : `Invalid input: ${message}`
|
|
6750
|
+
);
|
|
6751
|
+
}
|
|
6752
|
+
return result.data;
|
|
6753
|
+
}
|
|
6754
|
+
function assertString(value, name) {
|
|
6755
|
+
if (typeof value !== "string") throw new Error(`${name} must be a string`);
|
|
6756
|
+
}
|
|
6757
|
+
function assertOptionalString(value, name) {
|
|
6758
|
+
if (value !== void 0 && typeof value !== "string") {
|
|
6759
|
+
throw new Error(`${name} must be a string`);
|
|
6760
|
+
}
|
|
6761
|
+
}
|
|
6762
|
+
function assertNumber(value, name) {
|
|
6763
|
+
if (typeof value !== "number" || Number.isNaN(value)) {
|
|
6764
|
+
throw new Error(`${name} must be a number`);
|
|
6765
|
+
}
|
|
6766
|
+
}
|
|
6767
|
+
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
6768
|
+
function isValidEmail$1(value) {
|
|
6769
|
+
return EMAIL_RE.test(value.trim());
|
|
6770
|
+
}
|
|
6771
|
+
function getActiveTabInfo(tabManager) {
|
|
6772
|
+
const tab = tabManager.getActiveTab();
|
|
6773
|
+
if (!tab) return null;
|
|
6774
|
+
const wc = tab.view.webContents;
|
|
6775
|
+
if (wc.isDestroyed()) return null;
|
|
6776
|
+
return { tab, wc };
|
|
6777
|
+
}
|
|
6778
|
+
function sendSafe(wc, channel, ...args) {
|
|
6779
|
+
if (!wc || wc.isDestroyed()) return;
|
|
6780
|
+
try {
|
|
6781
|
+
wc.send(channel, ...args);
|
|
6782
|
+
} catch {
|
|
6783
|
+
}
|
|
6784
|
+
}
|
|
6702
6785
|
function setSidebarPanelMode(state2, mode, reason = "user") {
|
|
6703
6786
|
state2.uiState.sidebarPanelMode = mode;
|
|
6704
6787
|
if (reason === "user") {
|
|
@@ -6741,15 +6824,8 @@ function getSidebarPanelState(state2) {
|
|
|
6741
6824
|
}
|
|
6742
6825
|
function emitSidebarPanelState(state2) {
|
|
6743
6826
|
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
|
-
}
|
|
6827
|
+
sendSafe(state2.chromeView.webContents, Channels.SIDEBAR_STATE_UPDATE, panelState);
|
|
6828
|
+
sendSafe(state2.sidebarView.webContents, Channels.SIDEBAR_STATE_UPDATE, panelState);
|
|
6753
6829
|
return panelState;
|
|
6754
6830
|
}
|
|
6755
6831
|
function isSidebarAttached(state2) {
|
|
@@ -7059,8 +7135,8 @@ function createMainWindow(onTabStateChange) {
|
|
|
7059
7135
|
};
|
|
7060
7136
|
const tabManager = new TabManager(mainWindow, onTabStateChange);
|
|
7061
7137
|
const sendToRendererViews = (channel, ...args) => {
|
|
7062
|
-
chromeView.webContents
|
|
7063
|
-
sidebarView.webContents
|
|
7138
|
+
sendSafe(chromeView.webContents, channel, ...args);
|
|
7139
|
+
sendSafe(sidebarView.webContents, channel, ...args);
|
|
7064
7140
|
};
|
|
7065
7141
|
tabManager.onPageLoad((url, wc) => {
|
|
7066
7142
|
const activeWc = tabManager.getActiveTab()?.view.webContents;
|
|
@@ -8171,7 +8247,7 @@ function recoverNarratedActionToolCalls(text, availableToolNames) {
|
|
|
8171
8247
|
}
|
|
8172
8248
|
return recovered;
|
|
8173
8249
|
}
|
|
8174
|
-
const logger$
|
|
8250
|
+
const logger$o = createLogger("OpenAIProvider");
|
|
8175
8251
|
function shouldDebugAgentLoop() {
|
|
8176
8252
|
const value = process.env.VESSEL_DEBUG_AGENT_LOOP;
|
|
8177
8253
|
return value === "1" || value === "true";
|
|
@@ -8439,9 +8515,9 @@ function shouldRetryCompactToolLoop(profile, text, hasToolHistory, userMessage)
|
|
|
8439
8515
|
function logAgentLoopDebug(payload) {
|
|
8440
8516
|
if (!shouldDebugAgentLoop()) return;
|
|
8441
8517
|
try {
|
|
8442
|
-
logger$
|
|
8518
|
+
logger$o.info(`[agent-debug] ${JSON.stringify(payload)}`);
|
|
8443
8519
|
} catch (err) {
|
|
8444
|
-
logger$
|
|
8520
|
+
logger$o.warn("Failed to serialize debug payload:", err);
|
|
8445
8521
|
}
|
|
8446
8522
|
}
|
|
8447
8523
|
function formatOpenAICompatErrorMessage(providerId, message) {
|
|
@@ -9045,7 +9121,7 @@ function createLocalPkceOAuthFlow(config) {
|
|
|
9045
9121
|
isInProgress: () => activeFlow !== null
|
|
9046
9122
|
};
|
|
9047
9123
|
}
|
|
9048
|
-
const logger$
|
|
9124
|
+
const logger$n = createLogger("CodexOAuth");
|
|
9049
9125
|
const ISSUER = "https://auth.openai.com";
|
|
9050
9126
|
const CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
9051
9127
|
const SCOPE = "openid profile email offline_access api.connectors.read api.connectors.invoke";
|
|
@@ -9176,7 +9252,7 @@ function escapeHtml$1(text) {
|
|
|
9176
9252
|
}
|
|
9177
9253
|
const codexOAuth = createLocalPkceOAuthFlow({
|
|
9178
9254
|
name: "Codex",
|
|
9179
|
-
logger: logger$
|
|
9255
|
+
logger: logger$n,
|
|
9180
9256
|
preferredPorts: [PREFERRED_PORT$1, FALLBACK_PORT$1],
|
|
9181
9257
|
timeoutMs: AUTH_TIMEOUT_MS$1,
|
|
9182
9258
|
callbackPath: () => "/auth/callback",
|
|
@@ -9200,7 +9276,7 @@ async function startCodexOAuth(onStatus) {
|
|
|
9200
9276
|
function cancelCodexOAuth() {
|
|
9201
9277
|
codexOAuth.cancel();
|
|
9202
9278
|
}
|
|
9203
|
-
const logger$
|
|
9279
|
+
const logger$m = createLogger("CodexProvider");
|
|
9204
9280
|
const REFRESH_WINDOW_MS = 5 * 60 * 1e3;
|
|
9205
9281
|
const CODEX_BACKEND_BASE_URL = "https://chatgpt.com/backend-api/codex";
|
|
9206
9282
|
const CODEX_CLIENT_VERSION = "0.129.0";
|
|
@@ -9265,7 +9341,7 @@ class CodexProvider {
|
|
|
9265
9341
|
async ensureFreshTokens() {
|
|
9266
9342
|
if (Date.now() < this.tokens.expiresAt - REFRESH_WINDOW_MS) return;
|
|
9267
9343
|
try {
|
|
9268
|
-
logger$
|
|
9344
|
+
logger$m.info("Refreshing Codex access token");
|
|
9269
9345
|
const fresh = await refreshAccessToken(this.tokens);
|
|
9270
9346
|
this.tokens = fresh;
|
|
9271
9347
|
writeStoredCodexTokens(fresh);
|
|
@@ -9413,7 +9489,7 @@ class CodexProvider {
|
|
|
9413
9489
|
} catch (err) {
|
|
9414
9490
|
if (err.name !== "AbortError") {
|
|
9415
9491
|
const msg = err instanceof Error ? err.message : String(err);
|
|
9416
|
-
logger$
|
|
9492
|
+
logger$m.error("Codex streamQuery error:", err);
|
|
9417
9493
|
onChunk(`
|
|
9418
9494
|
|
|
9419
9495
|
[Error: ${msg}]`);
|
|
@@ -9481,7 +9557,7 @@ class CodexProvider {
|
|
|
9481
9557
|
} catch (err) {
|
|
9482
9558
|
if (err.name !== "AbortError") {
|
|
9483
9559
|
const msg = err instanceof Error ? err.message : String(err);
|
|
9484
|
-
logger$
|
|
9560
|
+
logger$m.error("Codex streamAgentQuery error:", err);
|
|
9485
9561
|
onChunk(`
|
|
9486
9562
|
|
|
9487
9563
|
[Error: ${msg}]`);
|
|
@@ -9681,60 +9757,6 @@ function createProvider(config) {
|
|
|
9681
9757
|
}
|
|
9682
9758
|
return new OpenAICompatProvider(normalized);
|
|
9683
9759
|
}
|
|
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
9760
|
function buildSubAgentSystemPrompt(thread) {
|
|
9739
9761
|
const domainBlock = thread.blockedDomains.length > 0 ? `
|
|
9740
9762
|
BLOCKED DOMAINS (never visit): ${thread.blockedDomains.join(", ")}` : "";
|
|
@@ -10769,6 +10791,7 @@ function normalizeBookmarkMetadataUpdate(input) {
|
|
|
10769
10791
|
}
|
|
10770
10792
|
return normalized;
|
|
10771
10793
|
}
|
|
10794
|
+
const logger$l = createLogger("BookmarkManager");
|
|
10772
10795
|
const UNSORTED_ID = "unsorted";
|
|
10773
10796
|
const ARCHIVE_FOLDER_NAME = "Archive";
|
|
10774
10797
|
const NETSCAPE_BOOKMARKS_DOCTYPE = "<!DOCTYPE NETSCAPE-Bookmark-file-1>";
|
|
@@ -11340,7 +11363,8 @@ function importBookmarksFromJson(content) {
|
|
|
11340
11363
|
save$1();
|
|
11341
11364
|
emit$2();
|
|
11342
11365
|
}
|
|
11343
|
-
} catch {
|
|
11366
|
+
} catch (err) {
|
|
11367
|
+
logger$l.warn("Failed to import bookmarks from JSON:", err);
|
|
11344
11368
|
errors++;
|
|
11345
11369
|
}
|
|
11346
11370
|
return { imported, skipped, errors };
|
|
@@ -11740,7 +11764,7 @@ async function resolveSelector(wc, index, selector) {
|
|
|
11740
11764
|
if (typeof fallbackSelector === "string" && fallbackSelector) {
|
|
11741
11765
|
return fallbackSelector;
|
|
11742
11766
|
}
|
|
11743
|
-
const page = await extractContent(wc);
|
|
11767
|
+
const page = await extractContent$1(wc);
|
|
11744
11768
|
const extractedSelector = findSelectorByIndex(page, index);
|
|
11745
11769
|
if (extractedSelector) return extractedSelector;
|
|
11746
11770
|
return null;
|
|
@@ -14318,65 +14342,371 @@ function cartOrigin(url) {
|
|
|
14318
14342
|
return null;
|
|
14319
14343
|
}
|
|
14320
14344
|
}
|
|
14321
|
-
|
|
14322
|
-
|
|
14323
|
-
|
|
14324
|
-
|
|
14325
|
-
|
|
14326
|
-
|
|
14327
|
-
|
|
14328
|
-
|
|
14345
|
+
class TabMutex {
|
|
14346
|
+
queue = Promise.resolve();
|
|
14347
|
+
enqueue(fn) {
|
|
14348
|
+
const run = this.queue.then(fn, fn);
|
|
14349
|
+
this.queue = run.then(
|
|
14350
|
+
() => void 0,
|
|
14351
|
+
() => void 0
|
|
14352
|
+
);
|
|
14353
|
+
return run;
|
|
14354
|
+
}
|
|
14355
|
+
}
|
|
14356
|
+
const logger$j = createLogger("PageActions");
|
|
14357
|
+
const DEFAULT_PAGE_SCRIPT_TIMEOUT_MS = 1500;
|
|
14358
|
+
const PAGE_SCRIPT_TIMEOUT = /* @__PURE__ */ Symbol("page-script-timeout");
|
|
14359
|
+
function pageBusyError(action) {
|
|
14360
|
+
return `Error: Page is still busy; ${action} timed out waiting for page scripts. Retry in a moment.`;
|
|
14361
|
+
}
|
|
14362
|
+
async function loadPermittedUrl(wc, url) {
|
|
14363
|
+
const { assertPermittedNavigationURL: assertPermittedNavigationURL2 } = await Promise.resolve().then(() => urlSafety);
|
|
14364
|
+
assertPermittedNavigationURL2(url);
|
|
14365
|
+
await wc.loadURL(url);
|
|
14366
|
+
}
|
|
14367
|
+
async function executePageScript(wc, script, options) {
|
|
14368
|
+
if (wc.isDestroyed()) return null;
|
|
14369
|
+
const timeoutMs = Math.max(150, options?.timeoutMs ?? DEFAULT_PAGE_SCRIPT_TIMEOUT_MS);
|
|
14370
|
+
let timer = null;
|
|
14371
|
+
try {
|
|
14372
|
+
const result = await Promise.race([
|
|
14373
|
+
wc.executeJavaScript(script, options?.userGesture ?? false),
|
|
14374
|
+
new Promise((resolve) => {
|
|
14375
|
+
timer = setTimeout(() => resolve(PAGE_SCRIPT_TIMEOUT), timeoutMs);
|
|
14376
|
+
})
|
|
14377
|
+
]);
|
|
14378
|
+
if (result === PAGE_SCRIPT_TIMEOUT) {
|
|
14379
|
+
return PAGE_SCRIPT_TIMEOUT;
|
|
14329
14380
|
}
|
|
14330
|
-
|
|
14331
|
-
|
|
14332
|
-
|
|
14381
|
+
return result;
|
|
14382
|
+
} catch (err) {
|
|
14383
|
+
const label = options?.label ? ` (${options.label})` : "";
|
|
14384
|
+
logger$j.warn(`Failed to execute page script${label}:`, err);
|
|
14385
|
+
return null;
|
|
14386
|
+
} finally {
|
|
14387
|
+
if (timer) {
|
|
14388
|
+
clearTimeout(timer);
|
|
14333
14389
|
}
|
|
14334
|
-
return { folderId: folder2.id, folderName: folder2.name };
|
|
14335
|
-
}
|
|
14336
|
-
const folderName = typeof args.folderName === "string" && args.folderName.trim() ? args.folderName.trim() : typeof args.folder_name === "string" && args.folder_name.trim() ? args.folder_name.trim() : args.archive ? ARCHIVE_FOLDER_NAME : "";
|
|
14337
|
-
if (!folderName || folderName.toLowerCase() === "unsorted") {
|
|
14338
|
-
return {
|
|
14339
|
-
folderId: UNSORTED_ID,
|
|
14340
|
-
folderName: "Unsorted"
|
|
14341
|
-
};
|
|
14342
|
-
}
|
|
14343
|
-
const existing = findFolderByName(folderName);
|
|
14344
|
-
if (existing) {
|
|
14345
|
-
return { folderId: existing.id, folderName: existing.name };
|
|
14346
|
-
}
|
|
14347
|
-
const createIfMissing = args.createFolderIfMissing ?? args.create_folder_if_missing;
|
|
14348
|
-
if (createIfMissing === false) {
|
|
14349
|
-
return { folderName, error: `Folder "${folderName}" not found` };
|
|
14350
14390
|
}
|
|
14351
|
-
const folderSummary = typeof args.folderSummary === "string" && args.folderSummary.trim() ? args.folderSummary.trim() : typeof args.folder_summary === "string" && args.folder_summary.trim() ? args.folder_summary.trim() : void 0;
|
|
14352
|
-
const { folder } = ensureFolder(folderName, folderSummary);
|
|
14353
|
-
return {
|
|
14354
|
-
folderId: folder.id,
|
|
14355
|
-
folderName: folder.name,
|
|
14356
|
-
createdFolder: folder.name
|
|
14357
|
-
};
|
|
14358
|
-
}
|
|
14359
|
-
function formatFolderStatus(limit = 6) {
|
|
14360
|
-
const folders = listFolderOverviews();
|
|
14361
|
-
const summary = folders.slice(0, limit).map((folder) => `${folder.name} (${folder.count})`).join(", ");
|
|
14362
|
-
return `Folder status: ${summary}${folders.length > limit ? ", ..." : ""}`;
|
|
14363
14391
|
}
|
|
14364
|
-
function
|
|
14365
|
-
|
|
14366
|
-
|
|
14392
|
+
async function waitForJsReady(wc, timeout = 8e3) {
|
|
14393
|
+
const start = Date.now();
|
|
14394
|
+
while (Date.now() - start < timeout) {
|
|
14395
|
+
const ready = await executePageScript(wc, "1", {
|
|
14396
|
+
timeoutMs: 250,
|
|
14397
|
+
userGesture: true,
|
|
14398
|
+
label: "js-ready probe"
|
|
14399
|
+
});
|
|
14400
|
+
if (ready === 1) return;
|
|
14401
|
+
await sleep(250);
|
|
14367
14402
|
}
|
|
14368
|
-
return getFolder(folderId)?.name ?? folderId;
|
|
14369
14403
|
}
|
|
14370
|
-
function
|
|
14371
|
-
return
|
|
14404
|
+
function waitForPotentialNavigation(wc, beforeUrl, timeout = 2500) {
|
|
14405
|
+
return waitForPotentialNavigation$1(wc, beforeUrl, timeout, QUIET_NAVIGATION_WINDOW_MS);
|
|
14372
14406
|
}
|
|
14373
|
-
function
|
|
14374
|
-
|
|
14375
|
-
|
|
14376
|
-
|
|
14377
|
-
|
|
14407
|
+
function getGlanceExtractScript() {
|
|
14408
|
+
return `(function() {
|
|
14409
|
+
var vw = window.innerWidth || document.documentElement.clientWidth || 0;
|
|
14410
|
+
var vh = window.innerHeight || document.documentElement.clientHeight || 0;
|
|
14411
|
+
var sy = window.scrollY || window.pageYOffset || 0;
|
|
14412
|
+
|
|
14413
|
+
function inViewport(el) {
|
|
14414
|
+
var r = el.getBoundingClientRect();
|
|
14415
|
+
return r.bottom > 0 && r.top < vh && r.right > 0 && r.left < vw && r.width > 0 && r.height > 0;
|
|
14416
|
+
}
|
|
14417
|
+
|
|
14418
|
+
function label(el) {
|
|
14419
|
+
return (el.getAttribute('aria-label') || el.textContent || '').trim().slice(0, 120);
|
|
14420
|
+
}
|
|
14421
|
+
|
|
14422
|
+
// Headings visible on screen
|
|
14423
|
+
var headings = [];
|
|
14424
|
+
document.querySelectorAll('h1, h2, h3, h4').forEach(function(h) {
|
|
14425
|
+
if (!inViewport(h)) return;
|
|
14426
|
+
var t = (h.textContent || '').trim();
|
|
14427
|
+
if (t && t.length < 200) headings.push(h.tagName.toLowerCase() + ': ' + t);
|
|
14428
|
+
});
|
|
14429
|
+
|
|
14430
|
+
// Links visible on screen (deduplicated by text)
|
|
14431
|
+
var links = [];
|
|
14432
|
+
var seenLinks = {};
|
|
14433
|
+
var idx = 1;
|
|
14434
|
+
document.querySelectorAll('a[href]').forEach(function(a) {
|
|
14435
|
+
if (!inViewport(a)) return;
|
|
14436
|
+
var t = (a.textContent || '').trim().slice(0, 100);
|
|
14437
|
+
if (!t || t.length < 2 || seenLinks[t]) return;
|
|
14438
|
+
seenLinks[t] = true;
|
|
14439
|
+
links.push({ text: t, href: (a.href || '').slice(0, 200), index: idx++ });
|
|
14440
|
+
});
|
|
14441
|
+
|
|
14442
|
+
// Buttons visible on screen
|
|
14443
|
+
var buttons = [];
|
|
14444
|
+
document.querySelectorAll('button, [role="button"], input[type="submit"], input[type="button"]').forEach(function(b) {
|
|
14445
|
+
if (!inViewport(b)) return;
|
|
14446
|
+
var t = label(b);
|
|
14447
|
+
if (!t || t.length < 1) return;
|
|
14448
|
+
buttons.push({ text: t, index: idx++ });
|
|
14449
|
+
});
|
|
14450
|
+
|
|
14451
|
+
// Input fields visible on screen
|
|
14452
|
+
var inputs = [];
|
|
14453
|
+
document.querySelectorAll('input:not([type="hidden"]):not([type="submit"]):not([type="button"]), select, textarea').forEach(function(inp) {
|
|
14454
|
+
if (!inViewport(inp)) return;
|
|
14455
|
+
var type = (inp.type || inp.tagName.toLowerCase() || '').toLowerCase();
|
|
14456
|
+
var lbl = (inp.getAttribute('aria-label') || inp.getAttribute('placeholder') || inp.name || '').trim();
|
|
14457
|
+
inputs.push({ type: type, label: lbl.slice(0, 80), placeholder: (inp.getAttribute('placeholder') || '').slice(0, 80), index: idx++ });
|
|
14458
|
+
});
|
|
14459
|
+
|
|
14460
|
+
// Content snapshot from main content area using textContent (instant, no reflow)
|
|
14461
|
+
var roots = ['main', 'article', '[role="main"]', '#content', '.content', '.story-body'];
|
|
14462
|
+
var contentRoot = null;
|
|
14463
|
+
for (var i = 0; i < roots.length; i++) {
|
|
14464
|
+
contentRoot = document.querySelector(roots[i]);
|
|
14465
|
+
if (contentRoot && contentRoot.textContent.trim().length > 50) break;
|
|
14466
|
+
contentRoot = null;
|
|
14467
|
+
}
|
|
14468
|
+
var snippet = '';
|
|
14469
|
+
if (contentRoot) {
|
|
14470
|
+
snippet = contentRoot.textContent.replace(/[ \\t]+/g, ' ').replace(/(\\n\\s*){3,}/g, '\\n\\n').trim().slice(0, 8000);
|
|
14471
|
+
} else {
|
|
14472
|
+
// Fallback: grab text from visible elements only
|
|
14473
|
+
var parts = [];
|
|
14474
|
+
document.querySelectorAll('h1, h2, h3, p, li, td, span, div').forEach(function(el) {
|
|
14475
|
+
if (parts.length > 100 || !inViewport(el)) return;
|
|
14476
|
+
var t = (el.textContent || '').trim();
|
|
14477
|
+
if (t.length > 10 && t.length < 500) parts.push(t);
|
|
14478
|
+
});
|
|
14479
|
+
snippet = parts.join('\\n').slice(0, 8000);
|
|
14480
|
+
}
|
|
14481
|
+
|
|
14482
|
+
return {
|
|
14483
|
+
title: document.title || '',
|
|
14484
|
+
url: location.href,
|
|
14485
|
+
headings: headings.slice(0, 20),
|
|
14486
|
+
links: links.slice(0, 40),
|
|
14487
|
+
buttons: buttons.slice(0, 20),
|
|
14488
|
+
inputs: inputs.slice(0, 15),
|
|
14489
|
+
contentSnippet: snippet,
|
|
14490
|
+
viewportHeight: vh,
|
|
14491
|
+
viewportWidth: vw,
|
|
14492
|
+
scrollY: Math.round(sy),
|
|
14493
|
+
};
|
|
14494
|
+
})()`;
|
|
14378
14495
|
}
|
|
14379
|
-
|
|
14496
|
+
async function glanceExtract(wc) {
|
|
14497
|
+
const startMs = Date.now();
|
|
14498
|
+
const result = await executePageScript(wc, getGlanceExtractScript(), { timeoutMs: 2500, label: "glance-extract" });
|
|
14499
|
+
const elapsed = Date.now() - startMs;
|
|
14500
|
+
if (!result || result === PAGE_SCRIPT_TIMEOUT) {
|
|
14501
|
+
return [
|
|
14502
|
+
`# ${wc.getTitle() || "(untitled)"}`,
|
|
14503
|
+
`URL: ${wc.getURL()}`,
|
|
14504
|
+
"",
|
|
14505
|
+
"[read_page mode=glance — page JS thread is completely blocked, no content available]",
|
|
14506
|
+
"[Try: click or type_text to interact directly, or wait a few seconds and retry]"
|
|
14507
|
+
].join("\n");
|
|
14508
|
+
}
|
|
14509
|
+
const sections = [
|
|
14510
|
+
`# ${result.title}`,
|
|
14511
|
+
`URL: ${result.url}`,
|
|
14512
|
+
`Viewport: ${result.viewportWidth}×${result.viewportHeight} scrollY=${result.scrollY}`,
|
|
14513
|
+
`[read_page mode=glance — ${elapsed}ms, showing what's visible on screen]`
|
|
14514
|
+
];
|
|
14515
|
+
if (result.headings.length > 0) {
|
|
14516
|
+
sections.push("", "## Headings", ...result.headings);
|
|
14517
|
+
}
|
|
14518
|
+
if (result.inputs.length > 0) {
|
|
14519
|
+
sections.push("", "## Input Fields");
|
|
14520
|
+
for (const inp of result.inputs) {
|
|
14521
|
+
const desc = inp.label || inp.placeholder || inp.type;
|
|
14522
|
+
sections.push(` [#${inp.index}] ${inp.type}: ${desc}`);
|
|
14523
|
+
}
|
|
14524
|
+
}
|
|
14525
|
+
if (result.buttons.length > 0) {
|
|
14526
|
+
sections.push("", "## Buttons");
|
|
14527
|
+
for (const btn of result.buttons) {
|
|
14528
|
+
sections.push(` [#${btn.index}] ${btn.text}`);
|
|
14529
|
+
}
|
|
14530
|
+
}
|
|
14531
|
+
if (result.links.length > 0) {
|
|
14532
|
+
sections.push("", "## Visible Links");
|
|
14533
|
+
for (const link of result.links) {
|
|
14534
|
+
sections.push(` [#${link.index}] ${link.text}`);
|
|
14535
|
+
}
|
|
14536
|
+
}
|
|
14537
|
+
if (result.contentSnippet) {
|
|
14538
|
+
const truncated = result.contentSnippet.length > 6e3 ? result.contentSnippet.slice(0, 6e3) + "\n[truncated]" : result.contentSnippet;
|
|
14539
|
+
sections.push("", "## Page Content (viewport)", "", truncated);
|
|
14540
|
+
}
|
|
14541
|
+
return sections.join("\n");
|
|
14542
|
+
}
|
|
14543
|
+
function normalizeReadPageMode(mode, pageContent) {
|
|
14544
|
+
if (typeof mode === "string") {
|
|
14545
|
+
const normalized = mode.trim().toLowerCase();
|
|
14546
|
+
if (normalized === "debug") return "debug";
|
|
14547
|
+
if (normalized === "glance") return "glance";
|
|
14548
|
+
if (normalized === "full" || normalized === "summary" || normalized === "interactives_only" || normalized === "forms_only" || normalized === "text_only" || normalized === "visible_only" || normalized === "results_only") {
|
|
14549
|
+
return normalized;
|
|
14550
|
+
}
|
|
14551
|
+
}
|
|
14552
|
+
return pageContent ? chooseAgentReadMode(pageContent) : "visible_only";
|
|
14553
|
+
}
|
|
14554
|
+
async function getPostNavSummary(wc) {
|
|
14555
|
+
const title = wc.getTitle();
|
|
14556
|
+
const titleLine = title ? `
|
|
14557
|
+
Page title: ${title}` : "";
|
|
14558
|
+
const overlaySignal = await executePageScript(
|
|
14559
|
+
wc,
|
|
14560
|
+
`(function() {
|
|
14561
|
+
var signals = [];
|
|
14562
|
+
var bodyStyle = window.getComputedStyle(document.body);
|
|
14563
|
+
var htmlStyle = window.getComputedStyle(document.documentElement);
|
|
14564
|
+
if (bodyStyle.overflow === 'hidden' || htmlStyle.overflow === 'hidden') {
|
|
14565
|
+
signals.push('body-scroll-locked');
|
|
14566
|
+
}
|
|
14567
|
+
var consentSelectors = [
|
|
14568
|
+
'#onetrust-consent-sdk', '#CybotCookiebotDialog', '[class*="consent-banner"]',
|
|
14569
|
+
'[class*="cookie-banner"]', '[class*="privacy-banner"]', '[id*="consent"]',
|
|
14570
|
+
'[class*="gdpr"]', '[data-testid*="consent"]', '[data-testid*="cookie"]',
|
|
14571
|
+
'.fc-consent-root', '#sp_message_container_', '[id*="trustarc"]',
|
|
14572
|
+
'[class*="cmp-"]', '[id*="cmp-"]'
|
|
14573
|
+
];
|
|
14574
|
+
for (var i = 0; i < consentSelectors.length; i++) {
|
|
14575
|
+
try {
|
|
14576
|
+
var el = document.querySelector(consentSelectors[i]);
|
|
14577
|
+
if (el && el.offsetHeight > 50) {
|
|
14578
|
+
signals.push('consent-banner:' + consentSelectors[i]);
|
|
14579
|
+
break;
|
|
14580
|
+
}
|
|
14581
|
+
} catch(e) {}
|
|
14582
|
+
}
|
|
14583
|
+
var vw = window.innerWidth || 0;
|
|
14584
|
+
var vh = window.innerHeight || 0;
|
|
14585
|
+
var vpArea = Math.max(1, vw * vh);
|
|
14586
|
+
var els = document.querySelectorAll('dialog[open], [role="dialog"], [aria-modal="true"]');
|
|
14587
|
+
if (els.length > 0) signals.push('dialog-open');
|
|
14588
|
+
if (signals.length === 0) {
|
|
14589
|
+
var fixed = document.querySelectorAll('div[style*="position: fixed"], div[style*="position:fixed"]');
|
|
14590
|
+
for (var j = 0; j < fixed.length && j < 20; j++) {
|
|
14591
|
+
var r = fixed[j].getBoundingClientRect();
|
|
14592
|
+
if ((r.width * r.height) / vpArea > 0.3) {
|
|
14593
|
+
signals.push('large-fixed-overlay');
|
|
14594
|
+
break;
|
|
14595
|
+
}
|
|
14596
|
+
}
|
|
14597
|
+
}
|
|
14598
|
+
return signals.length > 0 ? signals.join(', ') : null;
|
|
14599
|
+
})()`,
|
|
14600
|
+
{ timeoutMs: 1500, label: "overlay-probe" }
|
|
14601
|
+
);
|
|
14602
|
+
if (overlaySignal && overlaySignal !== PAGE_SCRIPT_TIMEOUT) {
|
|
14603
|
+
return `${titleLine}
|
|
14604
|
+
WARNING: Blocking overlay detected (${overlaySignal}). Call clear_overlays or accept_cookies before reading the page.`;
|
|
14605
|
+
}
|
|
14606
|
+
return titleLine;
|
|
14607
|
+
}
|
|
14608
|
+
async function getPostSearchSummary(wc) {
|
|
14609
|
+
await waitForLoad(wc, 2e3);
|
|
14610
|
+
try {
|
|
14611
|
+
const content = await Promise.race([
|
|
14612
|
+
extractContent$1(wc),
|
|
14613
|
+
new Promise((resolve) => setTimeout(() => resolve(null), 2500))
|
|
14614
|
+
]);
|
|
14615
|
+
if (content && content.content.length > 0) {
|
|
14616
|
+
const scoped = buildScopedContext(content, "results_only");
|
|
14617
|
+
const truncated = scoped.length > 2600 ? `${scoped.slice(0, 2600)}
|
|
14618
|
+
[Search results snapshot truncated...]` : scoped;
|
|
14619
|
+
return `
|
|
14620
|
+
Search results snapshot:
|
|
14621
|
+
${truncated}`;
|
|
14622
|
+
}
|
|
14623
|
+
} catch (err) {
|
|
14624
|
+
logger$j.warn("Failed to build post-search summary, falling back to nav summary:", err);
|
|
14625
|
+
}
|
|
14626
|
+
const fallback = await getPostNavSummary(wc);
|
|
14627
|
+
return fallback ? `${fallback}
|
|
14628
|
+
Search results snapshot unavailable. Use read_page(mode="results_only") if needed.` : `
|
|
14629
|
+
Search results snapshot unavailable. Use read_page(mode="results_only") if needed.`;
|
|
14630
|
+
}
|
|
14631
|
+
async function getPostClickNavSummary(wc, toolProfile) {
|
|
14632
|
+
try {
|
|
14633
|
+
const content = await Promise.race([
|
|
14634
|
+
extractContent$1(wc),
|
|
14635
|
+
new Promise((resolve) => setTimeout(() => resolve(null), 3e3))
|
|
14636
|
+
]);
|
|
14637
|
+
if (content && content.content.length > 0) {
|
|
14638
|
+
const scoped = toolProfile === "compact" ? buildCompactScopedContext(content, "visible_only") : buildScopedContext(content, "visible_only");
|
|
14639
|
+
const maxLen = toolProfile === "compact" ? 1800 : 3e3;
|
|
14640
|
+
const truncated = scoped.length > maxLen ? `${scoped.slice(0, maxLen)}
|
|
14641
|
+
[Page snapshot truncated. Use read_page for full details.]` : scoped;
|
|
14642
|
+
return `
|
|
14643
|
+
Page snapshot after navigation:
|
|
14644
|
+
${truncated}`;
|
|
14645
|
+
}
|
|
14646
|
+
} catch (err) {
|
|
14647
|
+
logger$j.warn("Failed to build post-click navigation summary:", err);
|
|
14648
|
+
}
|
|
14649
|
+
return "";
|
|
14650
|
+
}
|
|
14651
|
+
function resolveBookmarkFolderTarget$1(args) {
|
|
14652
|
+
const folderId = typeof args.folderId === "string" ? args.folderId.trim() : typeof args.folder_id === "string" ? args.folder_id.trim() : "";
|
|
14653
|
+
if (folderId) {
|
|
14654
|
+
if (folderId === UNSORTED_ID) {
|
|
14655
|
+
return {
|
|
14656
|
+
folderId: UNSORTED_ID,
|
|
14657
|
+
folderName: "Unsorted"
|
|
14658
|
+
};
|
|
14659
|
+
}
|
|
14660
|
+
const folder2 = getFolder(folderId);
|
|
14661
|
+
if (!folder2) {
|
|
14662
|
+
return { folderName: "Unsorted", error: `Folder ${folderId} not found` };
|
|
14663
|
+
}
|
|
14664
|
+
return { folderId: folder2.id, folderName: folder2.name };
|
|
14665
|
+
}
|
|
14666
|
+
const folderName = typeof args.folderName === "string" && args.folderName.trim() ? args.folderName.trim() : typeof args.folder_name === "string" && args.folder_name.trim() ? args.folder_name.trim() : args.archive ? ARCHIVE_FOLDER_NAME : "";
|
|
14667
|
+
if (!folderName || folderName.toLowerCase() === "unsorted") {
|
|
14668
|
+
return {
|
|
14669
|
+
folderId: UNSORTED_ID,
|
|
14670
|
+
folderName: "Unsorted"
|
|
14671
|
+
};
|
|
14672
|
+
}
|
|
14673
|
+
const existing = findFolderByName(folderName);
|
|
14674
|
+
if (existing) {
|
|
14675
|
+
return { folderId: existing.id, folderName: existing.name };
|
|
14676
|
+
}
|
|
14677
|
+
const createIfMissing = args.createFolderIfMissing ?? args.create_folder_if_missing;
|
|
14678
|
+
if (createIfMissing === false) {
|
|
14679
|
+
return { folderName, error: `Folder "${folderName}" not found` };
|
|
14680
|
+
}
|
|
14681
|
+
const folderSummary = typeof args.folderSummary === "string" && args.folderSummary.trim() ? args.folderSummary.trim() : typeof args.folder_summary === "string" && args.folder_summary.trim() ? args.folder_summary.trim() : void 0;
|
|
14682
|
+
const { folder } = ensureFolder(folderName, folderSummary);
|
|
14683
|
+
return {
|
|
14684
|
+
folderId: folder.id,
|
|
14685
|
+
folderName: folder.name,
|
|
14686
|
+
createdFolder: folder.name
|
|
14687
|
+
};
|
|
14688
|
+
}
|
|
14689
|
+
function formatFolderStatus(limit = 6) {
|
|
14690
|
+
const folders = listFolderOverviews();
|
|
14691
|
+
const summary = folders.slice(0, limit).map((folder) => `${folder.name} (${folder.count})`).join(", ");
|
|
14692
|
+
return `Folder status: ${summary}${folders.length > limit ? ", ..." : ""}`;
|
|
14693
|
+
}
|
|
14694
|
+
function describeFolder$1(folderId) {
|
|
14695
|
+
if (!folderId || folderId === UNSORTED_ID) {
|
|
14696
|
+
return "Unsorted";
|
|
14697
|
+
}
|
|
14698
|
+
return getFolder(folderId)?.name ?? folderId;
|
|
14699
|
+
}
|
|
14700
|
+
function composeDuplicateBookmarkResponse$1(args) {
|
|
14701
|
+
return `Bookmark already exists for ${args.url} in "${args.folderName}" (id=${args.bookmarkId}). Retry with onDuplicate="update" to refresh the existing bookmark or onDuplicate="duplicate" to keep both entries.`;
|
|
14702
|
+
}
|
|
14703
|
+
function composeFolderAwareResponse$1(message, createdFolder) {
|
|
14704
|
+
const prefix = createdFolder ? `Created folder "${createdFolder}".
|
|
14705
|
+
` : "";
|
|
14706
|
+
return `${prefix}${message}
|
|
14707
|
+
${formatFolderStatus()}`;
|
|
14708
|
+
}
|
|
14709
|
+
const HUGGING_FACE_HUB_HOSTS = /* @__PURE__ */ new Set(["huggingface.co", "www.huggingface.co"]);
|
|
14380
14710
|
const HUGGING_FACE_MODEL_TASKS = [
|
|
14381
14711
|
{
|
|
14382
14712
|
value: "automatic-speech-recognition",
|
|
@@ -14613,423 +14943,106 @@ function buildHuggingFaceSearchShortcut(currentUrl, rawQuery) {
|
|
|
14613
14943
|
const parameterResult = mapHuggingFaceParameterBucket(remainingQuery);
|
|
14614
14944
|
remainingQuery = parameterResult.remainingQuery;
|
|
14615
14945
|
if (parameterResult.value && parameterResult.label) {
|
|
14616
|
-
target.searchParams.append("num_parameters", parameterResult.value);
|
|
14617
|
-
appliedFilters.push(parameterResult.label);
|
|
14618
|
-
}
|
|
14619
|
-
}
|
|
14620
|
-
remainingQuery = collapseSearchTerms(
|
|
14621
|
-
remainingQuery.replace(/\bmodels?\b/gi, " ").replace(/\bdatasets?\b/gi, " ").replace(/\bspaces?\b/gi, " ").replace(/\bapps?\b/gi, " ")
|
|
14622
|
-
);
|
|
14623
|
-
if (remainingQuery) {
|
|
14624
|
-
target.searchParams.set("search", remainingQuery);
|
|
14625
|
-
}
|
|
14626
|
-
if (!remainingQuery && appliedFilters.length === 0) {
|
|
14627
|
-
return null;
|
|
14628
|
-
}
|
|
14629
|
-
if (section === "spaces" && remainingQuery) {
|
|
14630
|
-
target.searchParams.set("includeNonRunning", "true");
|
|
14631
|
-
}
|
|
14632
|
-
return {
|
|
14633
|
-
url: target.toString(),
|
|
14634
|
-
source: "Hugging Face",
|
|
14635
|
-
section,
|
|
14636
|
-
appliedFilters
|
|
14637
|
-
};
|
|
14638
|
-
}
|
|
14639
|
-
function normalizeSearchQuery(query) {
|
|
14640
|
-
return query.replace(/\s+/g, " ").trim();
|
|
14641
|
-
}
|
|
14642
|
-
const COMMON_SEARCH_QUERY_PARAMS = [
|
|
14643
|
-
"search",
|
|
14644
|
-
"q",
|
|
14645
|
-
"query",
|
|
14646
|
-
"keyword",
|
|
14647
|
-
"keywords",
|
|
14648
|
-
"term",
|
|
14649
|
-
"text"
|
|
14650
|
-
];
|
|
14651
|
-
const COMMON_PAGINATION_PARAMS = [
|
|
14652
|
-
"p",
|
|
14653
|
-
"page",
|
|
14654
|
-
"offset",
|
|
14655
|
-
"start",
|
|
14656
|
-
"cursor",
|
|
14657
|
-
"skip"
|
|
14658
|
-
];
|
|
14659
|
-
function looksLikeSearchResultsPath(pathname) {
|
|
14660
|
-
return /\/(search|results|browse|discover|find)(\/|$)/i.test(pathname);
|
|
14661
|
-
}
|
|
14662
|
-
function buildCommonSearchUrlShortcut(currentUrl, rawQuery) {
|
|
14663
|
-
let url;
|
|
14664
|
-
try {
|
|
14665
|
-
url = new URL(currentUrl);
|
|
14666
|
-
} catch {
|
|
14667
|
-
return null;
|
|
14668
|
-
}
|
|
14669
|
-
if (!/^https?:$/i.test(url.protocol)) {
|
|
14670
|
-
return null;
|
|
14671
|
-
}
|
|
14672
|
-
const query = normalizeSearchQuery(rawQuery);
|
|
14673
|
-
if (!query) return null;
|
|
14674
|
-
const existingParam = COMMON_SEARCH_QUERY_PARAMS.find(
|
|
14675
|
-
(param) => url.searchParams.has(param)
|
|
14676
|
-
);
|
|
14677
|
-
if (!existingParam && !looksLikeSearchResultsPath(url.pathname)) {
|
|
14678
|
-
return null;
|
|
14679
|
-
}
|
|
14680
|
-
const target = new URL(url.toString());
|
|
14681
|
-
const searchParam = existingParam ?? "q";
|
|
14682
|
-
target.searchParams.set(searchParam, query);
|
|
14683
|
-
for (const param of COMMON_PAGINATION_PARAMS) {
|
|
14684
|
-
target.searchParams.delete(param);
|
|
14685
|
-
}
|
|
14686
|
-
if (target.toString() === url.toString()) {
|
|
14687
|
-
return null;
|
|
14688
|
-
}
|
|
14689
|
-
return {
|
|
14690
|
-
url: target.toString(),
|
|
14691
|
-
source: "page URL",
|
|
14692
|
-
appliedFilters: existingParam ? [`updated ${existingParam} query`] : []
|
|
14693
|
-
};
|
|
14694
|
-
}
|
|
14695
|
-
function buildDefaultEngineShortcut(rawQuery) {
|
|
14696
|
-
const settings2 = loadSettings();
|
|
14697
|
-
const engineId = settings2.defaultSearchEngine ?? "duckduckgo";
|
|
14698
|
-
if (engineId === "none") return null;
|
|
14699
|
-
const preset = SEARCH_ENGINE_PRESETS[engineId];
|
|
14700
|
-
if (!preset) return null;
|
|
14701
|
-
const query = normalizeSearchQuery(rawQuery);
|
|
14702
|
-
if (!query) return null;
|
|
14703
|
-
return {
|
|
14704
|
-
url: preset.url + encodeURIComponent(query),
|
|
14705
|
-
source: "default search engine",
|
|
14706
|
-
appliedFilters: []
|
|
14707
|
-
};
|
|
14708
|
-
}
|
|
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
|
-
function getBookmarkMetadataFromArgs(args) {
|
|
14722
|
-
return normalizeBookmarkMetadata({
|
|
14723
|
-
intent: args.intent ?? args.intent,
|
|
14724
|
-
expectedContent: args.expectedContent ?? args.expected_content,
|
|
14725
|
-
keyFields: args.keyFields ?? args.key_fields,
|
|
14726
|
-
agentHints: args.agentHints ?? args.agent_hints
|
|
14727
|
-
});
|
|
14728
|
-
}
|
|
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;
|
|
14946
|
+
target.searchParams.append("num_parameters", parameterResult.value);
|
|
14947
|
+
appliedFilters.push(parameterResult.label);
|
|
14882
14948
|
}
|
|
14883
14949
|
}
|
|
14884
|
-
|
|
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
|
|
14950
|
+
remainingQuery = collapseSearchTerms(
|
|
14951
|
+
remainingQuery.replace(/\bmodels?\b/gi, " ").replace(/\bdatasets?\b/gi, " ").replace(/\bspaces?\b/gi, " ").replace(/\bapps?\b/gi, " ")
|
|
14891
14952
|
);
|
|
14892
|
-
|
|
14893
|
-
|
|
14894
|
-
|
|
14895
|
-
|
|
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);
|
|
14953
|
+
if (remainingQuery) {
|
|
14954
|
+
target.searchParams.set("search", remainingQuery);
|
|
14955
|
+
}
|
|
14956
|
+
if (!remainingQuery && appliedFilters.length === 0) {
|
|
14907
14957
|
return null;
|
|
14908
|
-
} finally {
|
|
14909
|
-
if (timer) {
|
|
14910
|
-
clearTimeout(timer);
|
|
14911
|
-
}
|
|
14912
14958
|
}
|
|
14913
|
-
|
|
14914
|
-
|
|
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);
|
|
14959
|
+
if (section === "spaces" && remainingQuery) {
|
|
14960
|
+
target.searchParams.set("includeNonRunning", "true");
|
|
14924
14961
|
}
|
|
14962
|
+
return {
|
|
14963
|
+
url: target.toString(),
|
|
14964
|
+
source: "Hugging Face",
|
|
14965
|
+
section,
|
|
14966
|
+
appliedFilters
|
|
14967
|
+
};
|
|
14925
14968
|
}
|
|
14926
|
-
function
|
|
14927
|
-
return
|
|
14928
|
-
wc,
|
|
14929
|
-
beforeUrl,
|
|
14930
|
-
timeout,
|
|
14931
|
-
QUIET_NAVIGATION_WINDOW_MS
|
|
14932
|
-
);
|
|
14969
|
+
function normalizeSearchQuery(query) {
|
|
14970
|
+
return query.replace(/\s+/g, " ").trim();
|
|
14933
14971
|
}
|
|
14934
|
-
|
|
14935
|
-
|
|
14936
|
-
|
|
14937
|
-
|
|
14938
|
-
|
|
14939
|
-
|
|
14940
|
-
|
|
14941
|
-
|
|
14942
|
-
|
|
14943
|
-
|
|
14944
|
-
|
|
14945
|
-
|
|
14946
|
-
|
|
14947
|
-
|
|
14948
|
-
|
|
14949
|
-
|
|
14950
|
-
|
|
14951
|
-
|
|
14952
|
-
|
|
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;
|
|
14972
|
+
const COMMON_SEARCH_QUERY_PARAMS = [
|
|
14973
|
+
"search",
|
|
14974
|
+
"q",
|
|
14975
|
+
"query",
|
|
14976
|
+
"keyword",
|
|
14977
|
+
"keywords",
|
|
14978
|
+
"term",
|
|
14979
|
+
"text"
|
|
14980
|
+
];
|
|
14981
|
+
const COMMON_PAGINATION_PARAMS = [
|
|
14982
|
+
"p",
|
|
14983
|
+
"page",
|
|
14984
|
+
"offset",
|
|
14985
|
+
"start",
|
|
14986
|
+
"cursor",
|
|
14987
|
+
"skip"
|
|
14988
|
+
];
|
|
14989
|
+
function looksLikeSearchResultsPath(pathname) {
|
|
14990
|
+
return /\/(search|results|browse|discover|find)(\/|$)/i.test(pathname);
|
|
14990
14991
|
}
|
|
14991
|
-
|
|
14992
|
-
|
|
14992
|
+
function buildCommonSearchUrlShortcut(currentUrl, rawQuery) {
|
|
14993
|
+
let url;
|
|
14993
14994
|
try {
|
|
14994
|
-
|
|
14995
|
-
|
|
14996
|
-
|
|
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);
|
|
14995
|
+
url = new URL(currentUrl);
|
|
14996
|
+
} catch {
|
|
14997
|
+
return null;
|
|
15008
14998
|
}
|
|
15009
|
-
|
|
15010
|
-
|
|
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);
|
|
14999
|
+
if (!/^https?:$/i.test(url.protocol)) {
|
|
15000
|
+
return null;
|
|
15031
15001
|
}
|
|
15032
|
-
|
|
15002
|
+
const query = normalizeSearchQuery(rawQuery);
|
|
15003
|
+
if (!query) return null;
|
|
15004
|
+
const existingParam = COMMON_SEARCH_QUERY_PARAMS.find(
|
|
15005
|
+
(param) => url.searchParams.has(param)
|
|
15006
|
+
);
|
|
15007
|
+
if (!existingParam && !looksLikeSearchResultsPath(url.pathname)) {
|
|
15008
|
+
return null;
|
|
15009
|
+
}
|
|
15010
|
+
const target = new URL(url.toString());
|
|
15011
|
+
const searchParam = existingParam ?? "q";
|
|
15012
|
+
target.searchParams.set(searchParam, query);
|
|
15013
|
+
for (const param of COMMON_PAGINATION_PARAMS) {
|
|
15014
|
+
target.searchParams.delete(param);
|
|
15015
|
+
}
|
|
15016
|
+
if (target.toString() === url.toString()) {
|
|
15017
|
+
return null;
|
|
15018
|
+
}
|
|
15019
|
+
return {
|
|
15020
|
+
url: target.toString(),
|
|
15021
|
+
source: "page URL",
|
|
15022
|
+
appliedFilters: existingParam ? [`updated ${existingParam} query`] : []
|
|
15023
|
+
};
|
|
15024
|
+
}
|
|
15025
|
+
function buildDefaultEngineShortcut(rawQuery) {
|
|
15026
|
+
const settings2 = loadSettings();
|
|
15027
|
+
const engineId = settings2.defaultSearchEngine ?? "duckduckgo";
|
|
15028
|
+
if (engineId === "none") return null;
|
|
15029
|
+
const preset = SEARCH_ENGINE_PRESETS[engineId];
|
|
15030
|
+
if (!preset) return null;
|
|
15031
|
+
const query = normalizeSearchQuery(rawQuery);
|
|
15032
|
+
if (!query) return null;
|
|
15033
|
+
return {
|
|
15034
|
+
url: preset.url + encodeURIComponent(query),
|
|
15035
|
+
source: "default search engine",
|
|
15036
|
+
appliedFilters: []
|
|
15037
|
+
};
|
|
15038
|
+
}
|
|
15039
|
+
function getBookmarkMetadataFromArgs(args) {
|
|
15040
|
+
return normalizeBookmarkMetadata({
|
|
15041
|
+
intent: args.intent ?? args.intent,
|
|
15042
|
+
expectedContent: args.expectedContent ?? args.expected_content,
|
|
15043
|
+
keyFields: args.keyFields ?? args.key_fields,
|
|
15044
|
+
agentHints: args.agentHints ?? args.agent_hints
|
|
15045
|
+
});
|
|
15033
15046
|
}
|
|
15034
15047
|
async function scrollPage(wc, deltaY) {
|
|
15035
15048
|
const getScrollY = async () => {
|
|
@@ -15594,6 +15607,19 @@ Click one of these dialog actions. Do NOT click any other element.` : "";
|
|
|
15594
15607
|
return `
|
|
15595
15608
|
${overlayHint}${actionsSuffix}${cartSummary}`;
|
|
15596
15609
|
}
|
|
15610
|
+
async function followHrefFromClickResult(wc, beforeUrl, result, logMessage) {
|
|
15611
|
+
const hrefMatch = typeof result === "string" ? result.match(/\nhref: (https?:\/\/\S+)/) : null;
|
|
15612
|
+
if (!hrefMatch) return null;
|
|
15613
|
+
try {
|
|
15614
|
+
await loadPermittedUrl(wc, hrefMatch[1]);
|
|
15615
|
+
await waitForLoad(wc, 8e3);
|
|
15616
|
+
const hrefUrl = wc.getURL();
|
|
15617
|
+
if (hrefUrl !== beforeUrl) return `${result.split("\n")[0]} -> ${hrefUrl}`;
|
|
15618
|
+
} catch (err) {
|
|
15619
|
+
logger$j.warn(logMessage, err);
|
|
15620
|
+
}
|
|
15621
|
+
return null;
|
|
15622
|
+
}
|
|
15597
15623
|
async function clickResolvedSelector(wc, selector) {
|
|
15598
15624
|
if (selector.startsWith("__vessel_idx:")) {
|
|
15599
15625
|
const idx = Number(selector.slice("__vessel_idx:".length));
|
|
@@ -15636,16 +15662,13 @@ Go back and select a different product.`;
|
|
|
15636
15662
|
return `${result}${await buildCartSuccessSuffix(wc, beforeUrl2, idxOverlay)}`;
|
|
15637
15663
|
}
|
|
15638
15664
|
if (!idxOverlay) {
|
|
15639
|
-
const
|
|
15640
|
-
|
|
15641
|
-
|
|
15642
|
-
|
|
15643
|
-
|
|
15644
|
-
|
|
15645
|
-
|
|
15646
|
-
} catch {
|
|
15647
|
-
}
|
|
15648
|
-
}
|
|
15665
|
+
const hrefFallback = await followHrefFromClickResult(
|
|
15666
|
+
wc,
|
|
15667
|
+
beforeUrl2,
|
|
15668
|
+
result,
|
|
15669
|
+
"Failed to follow href fallback after click:"
|
|
15670
|
+
);
|
|
15671
|
+
if (hrefFallback) return hrefFallback;
|
|
15649
15672
|
}
|
|
15650
15673
|
return idxOverlay ? `${result}
|
|
15651
15674
|
${idxOverlay}` : `${result}
|
|
@@ -15703,16 +15726,13 @@ Go back and select a different product.`;
|
|
|
15703
15726
|
return `${result}${await buildCartSuccessSuffix(wc, beforeUrl2, shadowOverlay)}`;
|
|
15704
15727
|
}
|
|
15705
15728
|
if (!shadowOverlay) {
|
|
15706
|
-
const
|
|
15707
|
-
|
|
15708
|
-
|
|
15709
|
-
|
|
15710
|
-
|
|
15711
|
-
|
|
15712
|
-
|
|
15713
|
-
} catch {
|
|
15714
|
-
}
|
|
15715
|
-
}
|
|
15729
|
+
const hrefFallback = await followHrefFromClickResult(
|
|
15730
|
+
wc,
|
|
15731
|
+
beforeUrl2,
|
|
15732
|
+
result,
|
|
15733
|
+
"Failed to follow href fallback after shadow click:"
|
|
15734
|
+
);
|
|
15735
|
+
if (hrefFallback) return hrefFallback;
|
|
15716
15736
|
}
|
|
15717
15737
|
return shadowOverlay ? `${result}
|
|
15718
15738
|
${shadowOverlay}` : `${result}
|
|
@@ -19886,7 +19906,7 @@ function parse(raw) {
|
|
|
19886
19906
|
const items = Array.isArray(raw.items) ? raw.items : [];
|
|
19887
19907
|
return { items };
|
|
19888
19908
|
}
|
|
19889
|
-
|
|
19909
|
+
const state$2 = loadJsonFile({ filePath: filePath$1(), fallback: { items: [] }, parse });
|
|
19890
19910
|
const persistence$2 = createDebouncedJsonPersistence({
|
|
19891
19911
|
debounceMs: 250,
|
|
19892
19912
|
filePath: filePath$1(),
|
|
@@ -20188,8 +20208,8 @@ function registerPrivateIpcHandlers(state2) {
|
|
|
20188
20208
|
ipc.handle(Channels.OPEN_PRIVATE_WINDOW, () => {
|
|
20189
20209
|
createPrivateWindow();
|
|
20190
20210
|
});
|
|
20191
|
-
ipc.handle(Channels.OPEN_NEW_WINDOW, () => {
|
|
20192
|
-
const { createSecondaryWindow: createSecondaryWindow2 } =
|
|
20211
|
+
ipc.handle(Channels.OPEN_NEW_WINDOW, async () => {
|
|
20212
|
+
const { createSecondaryWindow: createSecondaryWindow2 } = await Promise.resolve().then(() => window$1);
|
|
20193
20213
|
createSecondaryWindow2();
|
|
20194
20214
|
});
|
|
20195
20215
|
ipc.handle(Channels.WINDOW_MINIMIZE, () => {
|
|
@@ -20254,9 +20274,7 @@ function createPrivateWindow() {
|
|
|
20254
20274
|
const tabManager = new TabManager(
|
|
20255
20275
|
win,
|
|
20256
20276
|
(tabs, activeId) => {
|
|
20257
|
-
|
|
20258
|
-
chromeView.webContents.send(Channels.TAB_STATE_UPDATE, tabs, activeId);
|
|
20259
|
-
}
|
|
20277
|
+
sendSafe(chromeView.webContents, Channels.TAB_STATE_UPDATE, tabs, activeId);
|
|
20260
20278
|
layoutPrivateViews(state2);
|
|
20261
20279
|
},
|
|
20262
20280
|
{ isPrivate: true, sessionPartition: privateSessionPartition }
|
|
@@ -20293,6 +20311,10 @@ function createPrivateWindow() {
|
|
|
20293
20311
|
logger$h.info("Private browsing window opened");
|
|
20294
20312
|
return state2;
|
|
20295
20313
|
}
|
|
20314
|
+
const window$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
20315
|
+
__proto__: null,
|
|
20316
|
+
createPrivateWindow
|
|
20317
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
20296
20318
|
const secondaryWindows = /* @__PURE__ */ new Set();
|
|
20297
20319
|
function layoutSecondaryViews(state2) {
|
|
20298
20320
|
const { window: win, chromeView, tabManager } = state2;
|
|
@@ -20408,8 +20430,8 @@ function registerSecondaryIpcHandlers(state2) {
|
|
|
20408
20430
|
(_e, groupId) => showGroupContextMenu(state2.tabManager, groupId, state2.window)
|
|
20409
20431
|
);
|
|
20410
20432
|
ipc.handle(Channels.OPEN_NEW_WINDOW, () => createSecondaryWindow());
|
|
20411
|
-
ipc.handle(Channels.OPEN_PRIVATE_WINDOW, () => {
|
|
20412
|
-
const { createPrivateWindow: createPrivateWindow2 } =
|
|
20433
|
+
ipc.handle(Channels.OPEN_PRIVATE_WINDOW, async () => {
|
|
20434
|
+
const { createPrivateWindow: createPrivateWindow2 } = await Promise.resolve().then(() => window$2);
|
|
20413
20435
|
createPrivateWindow2();
|
|
20414
20436
|
});
|
|
20415
20437
|
ipc.handle(Channels.IS_PRIVATE_MODE, () => false);
|
|
@@ -20461,9 +20483,7 @@ function createSecondaryWindow() {
|
|
|
20461
20483
|
chromeView.setBackgroundColor("#00000000");
|
|
20462
20484
|
win.contentView.addChildView(chromeView);
|
|
20463
20485
|
const tabManager = new TabManager(win, (tabs, activeId) => {
|
|
20464
|
-
|
|
20465
|
-
chromeView.webContents.send(Channels.TAB_STATE_UPDATE, tabs, activeId);
|
|
20466
|
-
}
|
|
20486
|
+
sendSafe(chromeView.webContents, Channels.TAB_STATE_UPDATE, tabs, activeId);
|
|
20467
20487
|
layoutSecondaryViews(state2);
|
|
20468
20488
|
});
|
|
20469
20489
|
const state2 = { window: win, chromeView, tabManager };
|
|
@@ -20487,12 +20507,16 @@ function createSecondaryWindow() {
|
|
|
20487
20507
|
win.show();
|
|
20488
20508
|
return state2;
|
|
20489
20509
|
}
|
|
20510
|
+
const window$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
20511
|
+
__proto__: null,
|
|
20512
|
+
createSecondaryWindow
|
|
20513
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
20490
20514
|
const TabIdSchema = zod.z.string().min(1);
|
|
20491
20515
|
const GroupIdSchema = zod.z.string().min(1);
|
|
20492
20516
|
const UrlSchema = zod.z.string().min(1);
|
|
20493
20517
|
const ColorSchema = zod.z.string().min(1);
|
|
20494
20518
|
const FindActionSchema = zod.z.enum(["clearSelection", "keepSelection", "activateSelection"]);
|
|
20495
|
-
function registerTabHandlers(windowState,
|
|
20519
|
+
function registerTabHandlers(windowState, _sendToRendererViews) {
|
|
20496
20520
|
const { tabManager, mainWindow } = windowState;
|
|
20497
20521
|
electron.ipcMain.handle(Channels.OPEN_PRIVATE_WINDOW, (event) => {
|
|
20498
20522
|
assertTrustedIpcSender(event);
|
|
@@ -21131,7 +21155,7 @@ async function handleAIQuery(query, provider, activeWebContents, onChunk, onEnd,
|
|
|
21131
21155
|
const isSummarize = lowerQuery.startsWith("summarize") || lowerQuery.startsWith("tldr") || lowerQuery === "summary";
|
|
21132
21156
|
if (provider.streamAgentQuery && tabManager && activeWebContents && runtime2) {
|
|
21133
21157
|
try {
|
|
21134
|
-
const pageContent = await extractContent(activeWebContents);
|
|
21158
|
+
const pageContent = await extractContent$1(activeWebContents);
|
|
21135
21159
|
const pageType = detectPageType(pageContent);
|
|
21136
21160
|
const defaultReadMode = chooseAgentReadMode(pageContent);
|
|
21137
21161
|
if (provider.agentToolProfile === "compact") {
|
|
@@ -21232,7 +21256,7 @@ ${trackerCtx}`;
|
|
|
21232
21256
|
let prompt;
|
|
21233
21257
|
if (activeWebContents) {
|
|
21234
21258
|
try {
|
|
21235
|
-
const pageContent = await extractContent(activeWebContents);
|
|
21259
|
+
const pageContent = await extractContent$1(activeWebContents);
|
|
21236
21260
|
if (isSummarize) {
|
|
21237
21261
|
prompt = buildSummarizePrompt(pageContent);
|
|
21238
21262
|
} else {
|
|
@@ -21492,7 +21516,7 @@ function registerContentHandlers(windowState) {
|
|
|
21492
21516
|
assertTrustedIpcSender(event);
|
|
21493
21517
|
const activeTab = tabManager.getActiveTab();
|
|
21494
21518
|
if (!activeTab) return null;
|
|
21495
|
-
return extractContent(activeTab.view.webContents);
|
|
21519
|
+
return extractContent$1(activeTab.view.webContents);
|
|
21496
21520
|
});
|
|
21497
21521
|
electron.ipcMain.handle(Channels.READER_MODE_TOGGLE, async (event) => {
|
|
21498
21522
|
assertTrustedIpcSender(event);
|
|
@@ -21506,7 +21530,7 @@ function registerContentHandlers(windowState) {
|
|
|
21506
21530
|
}
|
|
21507
21531
|
} else {
|
|
21508
21532
|
const originalUrl = activeTab.state.url;
|
|
21509
|
-
const content = await extractContent(activeTab.view.webContents);
|
|
21533
|
+
const content = await extractContent$1(activeTab.view.webContents);
|
|
21510
21534
|
const html = generateReaderHTML(content);
|
|
21511
21535
|
activeTab.setReaderMode(true, originalUrl);
|
|
21512
21536
|
void loadInternalDataURL(
|
|
@@ -22631,7 +22655,7 @@ function requiresExplicitMcpApproval(name, args) {
|
|
|
22631
22655
|
if (name === "remove_bookmark_folder" && args.delete_contents === true) return true;
|
|
22632
22656
|
return false;
|
|
22633
22657
|
}
|
|
22634
|
-
function getActiveTabSummary(tabManager) {
|
|
22658
|
+
function getActiveTabSummary$1(tabManager) {
|
|
22635
22659
|
const activeTab = tabManager.getActiveTab();
|
|
22636
22660
|
const activeTabId = tabManager.getActiveTabId();
|
|
22637
22661
|
if (!activeTab || !activeTabId) return null;
|
|
@@ -22671,7 +22695,7 @@ async function getPostActionState(tabManager, name) {
|
|
|
22671
22695
|
if (navActions.includes(name)) {
|
|
22672
22696
|
let warning = "";
|
|
22673
22697
|
try {
|
|
22674
|
-
const page = await extractContent(wc);
|
|
22698
|
+
const page = await extractContent$1(wc);
|
|
22675
22699
|
const issue = getRecoverableAccessIssue(page);
|
|
22676
22700
|
if (issue) {
|
|
22677
22701
|
const blockedUrl = wc.getURL();
|
|
@@ -22704,7 +22728,7 @@ async function getPostActionState(tabManager, name) {
|
|
|
22704
22728
|
}
|
|
22705
22729
|
if (tabActions.includes(name)) {
|
|
22706
22730
|
const activeId = tabManager.getActiveTabId();
|
|
22707
|
-
const active = getActiveTabSummary(tabManager);
|
|
22731
|
+
const active = getActiveTabSummary$1(tabManager);
|
|
22708
22732
|
const count = tabManager.getAllStates().length;
|
|
22709
22733
|
return `
|
|
22710
22734
|
[state: activeTab=${activeId}, title=${JSON.stringify(active?.title ?? "")}, url=${active?.url ?? ""}, totalTabs=${count}]`;
|
|
@@ -24148,7 +24172,7 @@ function registerTools(server, tabManager, runtime2) {
|
|
|
24148
24172
|
const wc = activeTab.view.webContents;
|
|
24149
24173
|
pageUrl = wc.getURL();
|
|
24150
24174
|
pageTitle = wc.getTitle();
|
|
24151
|
-
const page = await extractContent(wc);
|
|
24175
|
+
const page = await extractContent$1(wc);
|
|
24152
24176
|
pageType = detectPageType(page);
|
|
24153
24177
|
} catch (err) {
|
|
24154
24178
|
logger$a.warn("Failed to detect page type for tool scoring, falling back to GENERAL:", err);
|
|
@@ -24314,7 +24338,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
24314
24338
|
const tab = tabManager.getActiveTab();
|
|
24315
24339
|
if (!tab) return asNoActiveTabResponse();
|
|
24316
24340
|
try {
|
|
24317
|
-
const pageContent = await extractContent(tab.view.webContents);
|
|
24341
|
+
const pageContent = await extractContent$1(tab.view.webContents);
|
|
24318
24342
|
const effectiveMode = mode || "full";
|
|
24319
24343
|
return asTextResponse(
|
|
24320
24344
|
await buildExtractResponse(
|
|
@@ -24346,7 +24370,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
24346
24370
|
const tab = tabManager.getActiveTab();
|
|
24347
24371
|
if (!tab) return asNoActiveTabResponse();
|
|
24348
24372
|
try {
|
|
24349
|
-
const pageContent = await extractContent(tab.view.webContents);
|
|
24373
|
+
const pageContent = await extractContent$1(tab.view.webContents);
|
|
24350
24374
|
const effectiveMode = mode || "full";
|
|
24351
24375
|
return asTextResponse(
|
|
24352
24376
|
await buildExtractResponse(
|
|
@@ -24480,7 +24504,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
24480
24504
|
const tab = tabManager.getActiveTab();
|
|
24481
24505
|
if (!tab) return asNoActiveTabResponse();
|
|
24482
24506
|
try {
|
|
24483
|
-
const pageContent = await extractContent(tab.view.webContents);
|
|
24507
|
+
const pageContent = await extractContent$1(tab.view.webContents);
|
|
24484
24508
|
const requestedType = typeof type === "string" && type.trim() ? type.trim().toLowerCase() : "";
|
|
24485
24509
|
const entities = (pageContent.structuredData ?? []).filter(
|
|
24486
24510
|
(entity) => requestedType ? entity.types.some(
|
|
@@ -25583,7 +25607,7 @@ ${JSON.stringify(otherHighlights, null, 2)}`
|
|
|
25583
25607
|
"memory_page_capture",
|
|
25584
25608
|
{ title, folder, tags },
|
|
25585
25609
|
async () => {
|
|
25586
|
-
const page = await extractContent(tab.view.webContents);
|
|
25610
|
+
const page = await extractContent$1(tab.view.webContents);
|
|
25587
25611
|
const saved = capturePageToVault({
|
|
25588
25612
|
page,
|
|
25589
25613
|
title,
|
|
@@ -25704,7 +25728,7 @@ ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`
|
|
|
25704
25728
|
const wc = tab.view.webContents;
|
|
25705
25729
|
let page;
|
|
25706
25730
|
try {
|
|
25707
|
-
page = await extractContent(wc);
|
|
25731
|
+
page = await extractContent$1(wc);
|
|
25708
25732
|
} catch (err) {
|
|
25709
25733
|
logger$a.warn("Failed to extract page while generating suggestions:", err);
|
|
25710
25734
|
return asTextResponse(
|
|
@@ -25720,7 +25744,6 @@ ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`
|
|
|
25720
25744
|
suggestions.push(flowCtx);
|
|
25721
25745
|
suggestions.push("");
|
|
25722
25746
|
}
|
|
25723
|
-
page.url.toLowerCase();
|
|
25724
25747
|
const hasPasswordField = page.forms.some(
|
|
25725
25748
|
(f) => f.fields.some((el) => el.inputType === "password")
|
|
25726
25749
|
);
|
|
@@ -27263,7 +27286,7 @@ const BUNDLED_KIT_IDS = /* @__PURE__ */ new Set([
|
|
|
27263
27286
|
"price-scout",
|
|
27264
27287
|
"form-filler"
|
|
27265
27288
|
]);
|
|
27266
|
-
const KIT_ID_UNSAFE_CHAR_PATTERN = /[
|
|
27289
|
+
const KIT_ID_UNSAFE_CHAR_PATTERN = /[/\\\0]/;
|
|
27267
27290
|
function isSafeAutomationKitId(id) {
|
|
27268
27291
|
return id.length > 0 && !KIT_ID_UNSAFE_CHAR_PATTERN.test(id);
|
|
27269
27292
|
}
|
|
@@ -27294,7 +27317,8 @@ function getInstalledKits() {
|
|
|
27294
27317
|
let files;
|
|
27295
27318
|
try {
|
|
27296
27319
|
files = fs$1.readdirSync(dir).filter((f) => f.endsWith(".kit.json"));
|
|
27297
|
-
} catch {
|
|
27320
|
+
} catch (err) {
|
|
27321
|
+
logger$9.warn("Failed to read kit directory:", err);
|
|
27298
27322
|
return [];
|
|
27299
27323
|
}
|
|
27300
27324
|
const kits = [];
|
|
@@ -27325,13 +27349,15 @@ async function installKitFromFile() {
|
|
|
27325
27349
|
let raw;
|
|
27326
27350
|
try {
|
|
27327
27351
|
raw = fs$1.readFileSync(filePaths[0], "utf-8");
|
|
27328
|
-
} catch {
|
|
27352
|
+
} catch (err) {
|
|
27353
|
+
logger$9.warn("Failed to read selected kit file:", err);
|
|
27329
27354
|
return errorResult("Could not read the selected file.");
|
|
27330
27355
|
}
|
|
27331
27356
|
let parsed;
|
|
27332
27357
|
try {
|
|
27333
27358
|
parsed = JSON.parse(raw);
|
|
27334
|
-
} catch {
|
|
27359
|
+
} catch (err) {
|
|
27360
|
+
logger$9.warn("Selected kit file is not valid JSON:", err);
|
|
27335
27361
|
return errorResult("File is not valid JSON.");
|
|
27336
27362
|
}
|
|
27337
27363
|
if (!isValidKit(parsed)) {
|
|
@@ -27351,7 +27377,8 @@ async function installKitFromFile() {
|
|
|
27351
27377
|
}
|
|
27352
27378
|
try {
|
|
27353
27379
|
fs$1.writeFileSync(dest, JSON.stringify(parsed, null, 2), "utf-8");
|
|
27354
|
-
} catch {
|
|
27380
|
+
} catch (err) {
|
|
27381
|
+
logger$9.warn("Failed to save kit file:", err);
|
|
27355
27382
|
return errorResult("Failed to save the kit file.");
|
|
27356
27383
|
}
|
|
27357
27384
|
return okResult({ kit: parsed });
|
|
@@ -27376,7 +27403,8 @@ function uninstallKit(id, scheduledKitIds) {
|
|
|
27376
27403
|
try {
|
|
27377
27404
|
fs$1.unlinkSync(target);
|
|
27378
27405
|
return okResult();
|
|
27379
|
-
} catch {
|
|
27406
|
+
} catch (err) {
|
|
27407
|
+
logger$9.warn("Failed to remove kit file:", err);
|
|
27380
27408
|
return errorResult("Failed to remove the kit file.");
|
|
27381
27409
|
}
|
|
27382
27410
|
}
|
|
@@ -29133,7 +29161,7 @@ function registerAutofillHandlers(windowState) {
|
|
|
29133
29161
|
const activeTab = windowState.tabManager.getActiveTab();
|
|
29134
29162
|
const wc = activeTab?.view.webContents;
|
|
29135
29163
|
if (!wc) throw new Error("No active tab");
|
|
29136
|
-
const content = await extractContent(wc);
|
|
29164
|
+
const content = await extractContent$1(wc);
|
|
29137
29165
|
const elements = content.interactiveElements || [];
|
|
29138
29166
|
const matches = matchFields(elements, profile);
|
|
29139
29167
|
if (matches.length === 0) {
|
|
@@ -30785,25 +30813,12 @@ async function bootstrap() {
|
|
|
30785
30813
|
count = 0;
|
|
30786
30814
|
}
|
|
30787
30815
|
}
|
|
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
|
-
}
|
|
30816
|
+
sendSafe(state2.chromeView.webContents, Channels.HIGHLIGHT_COUNT_UPDATE, count);
|
|
30817
|
+
sendSafe(state2.sidebarView.webContents, Channels.HIGHLIGHT_COUNT_UPDATE, count);
|
|
30818
|
+
sendSafe(state2.devtoolsPanelView.webContents, Channels.HIGHLIGHT_COUNT_UPDATE, count);
|
|
30800
30819
|
};
|
|
30801
30820
|
const windowState = createMainWindow((tabs, activeId, meta) => {
|
|
30802
|
-
windowState.chromeView.webContents.
|
|
30803
|
-
Channels.TAB_STATE_UPDATE,
|
|
30804
|
-
tabs,
|
|
30805
|
-
activeId
|
|
30806
|
-
);
|
|
30821
|
+
sendSafe(windowState.chromeView.webContents, Channels.TAB_STATE_UPDATE, tabs, activeId);
|
|
30807
30822
|
void syncActiveHighlightCount(windowState);
|
|
30808
30823
|
layoutViews(windowState);
|
|
30809
30824
|
if (meta.persistSession) {
|
|
@@ -30826,18 +30841,12 @@ async function bootstrap() {
|
|
|
30826
30841
|
runtime = new AgentRuntime(tabManager);
|
|
30827
30842
|
installAdBlocking(tabManager);
|
|
30828
30843
|
setDevToolsPanelListener((state2) => {
|
|
30829
|
-
|
|
30830
|
-
devtoolsPanelView.webContents.send(Channels.DEVTOOLS_PANEL_STATE, state2);
|
|
30831
|
-
}
|
|
30844
|
+
sendSafe(devtoolsPanelView.webContents, Channels.DEVTOOLS_PANEL_STATE, state2);
|
|
30832
30845
|
});
|
|
30833
30846
|
registerIpcHandlers(windowState, runtime);
|
|
30834
30847
|
tabManager.onSecurityStateChange((tabId, state2) => {
|
|
30835
|
-
|
|
30836
|
-
|
|
30837
|
-
}
|
|
30838
|
-
if (!sidebarView.webContents.isDestroyed()) {
|
|
30839
|
-
sidebarView.webContents.send(Channels.SECURITY_STATE_UPDATE, { tabId, state: state2 });
|
|
30840
|
-
}
|
|
30848
|
+
sendSafe(chromeView.webContents, Channels.SECURITY_STATE_UPDATE, { tabId, state: state2 });
|
|
30849
|
+
sendSafe(sidebarView.webContents, Channels.SECURITY_STATE_UPDATE, { tabId, state: state2 });
|
|
30841
30850
|
});
|
|
30842
30851
|
registerHighlightShortcut(windowState.mainWindow, tabManager);
|
|
30843
30852
|
setupAppMenu({
|
|
@@ -30871,21 +30880,19 @@ async function bootstrap() {
|
|
|
30871
30880
|
}
|
|
30872
30881
|
},
|
|
30873
30882
|
clearBrowsingData: () => {
|
|
30874
|
-
|
|
30875
|
-
chromeView.webContents.send(Channels.CLEAR_BROWSING_DATA_OPEN);
|
|
30876
|
-
}
|
|
30883
|
+
sendSafe(chromeView.webContents, Channels.CLEAR_BROWSING_DATA_OPEN);
|
|
30877
30884
|
},
|
|
30878
30885
|
togglePictureInPicture: () => {
|
|
30879
30886
|
void togglePictureInPicture(tabManager);
|
|
30880
30887
|
}
|
|
30881
30888
|
});
|
|
30882
30889
|
subscribe((state2) => {
|
|
30883
|
-
chromeView.webContents
|
|
30884
|
-
sidebarView.webContents
|
|
30890
|
+
sendSafe(chromeView.webContents, Channels.BOOKMARKS_UPDATE, state2);
|
|
30891
|
+
sendSafe(sidebarView.webContents, Channels.BOOKMARKS_UPDATE, state2);
|
|
30885
30892
|
});
|
|
30886
30893
|
subscribe$1((state2) => {
|
|
30887
|
-
chromeView.webContents
|
|
30888
|
-
sidebarView.webContents
|
|
30894
|
+
sendSafe(chromeView.webContents, Channels.HISTORY_UPDATE, state2);
|
|
30895
|
+
sendSafe(sidebarView.webContents, Channels.HISTORY_UPDATE, state2);
|
|
30889
30896
|
});
|
|
30890
30897
|
installDownloadHandler(chromeView);
|
|
30891
30898
|
installPermissionHandler();
|