@quanta-intellect/vessel-browser 0.1.132 → 0.1.133

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 CHANGED
@@ -114,7 +114,7 @@ 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$v = createLogger("Settings");
117
+ const logger$x = createLogger("Settings");
118
118
  const SETTABLE_KEYS = new Set(Object.keys(defaults));
119
119
  let settings = null;
120
120
  let settingsIssues = [];
@@ -139,7 +139,7 @@ function canUseSafeStorage$1() {
139
139
  try {
140
140
  return electron.safeStorage.isEncryptionAvailable();
141
141
  } catch (err) {
142
- logger$v.warn("safeStorage.isEncryptionAvailable() failed, assuming unavailable:", err);
142
+ logger$x.warn("safeStorage.isEncryptionAvailable() failed, assuming unavailable:", err);
143
143
  return false;
144
144
  }
145
145
  }
@@ -148,7 +148,7 @@ function writePrivateFile(filePath2, data) {
148
148
  try {
149
149
  fs.chmodSync(filePath2, 384);
150
150
  } catch (err) {
151
- logger$v.debug("Could not chmod private file (non-POSIX filesystem):", err);
151
+ logger$x.debug("Could not chmod private file (non-POSIX filesystem):", err);
152
152
  }
153
153
  }
154
154
  function assertSafeStorageAvailable() {
@@ -167,7 +167,7 @@ function readStoredProviderSecret() {
167
167
  }
168
168
  } catch (err) {
169
169
  if (!isMissingFileError(err)) {
170
- logger$v.warn("Could not read stored provider secret:", err);
170
+ logger$x.warn("Could not read stored provider secret:", err);
171
171
  }
172
172
  }
173
173
  return null;
@@ -185,7 +185,7 @@ function clearStoredProviderSecret() {
185
185
  fs.unlinkSync(getChatProviderSecretPath());
186
186
  } catch (err) {
187
187
  if (!isMissingFileError(err)) {
188
- logger$v.warn("Could not delete provider secret file:", err);
188
+ logger$x.warn("Could not delete provider secret file:", err);
189
189
  }
190
190
  }
191
191
  }
@@ -203,7 +203,7 @@ function readStoredCodexTokens() {
203
203
  }
204
204
  } catch (err) {
205
205
  if (!isMissingFileError(err)) {
206
- logger$v.warn("Could not read stored Codex tokens:", err);
206
+ logger$x.warn("Could not read stored Codex tokens:", err);
207
207
  }
208
208
  }
209
209
  return null;
@@ -221,7 +221,7 @@ function clearStoredCodexTokens() {
221
221
  fs.unlinkSync(getCodexTokensPath());
222
222
  } catch (err) {
223
223
  if (!isMissingFileError(err)) {
224
- logger$v.warn("Could not delete Codex token file:", err);
224
+ logger$x.warn("Could not delete Codex token file:", err);
225
225
  }
226
226
  }
227
227
  }
@@ -351,7 +351,9 @@ function persistNow() {
351
351
  JSON.stringify(buildPersistedSettings(settings), null, 2),
352
352
  { encoding: "utf-8", mode: 384 }
353
353
  )
354
- ).then(() => fs.promises.chmod(getSettingsPath(), 384).catch(() => void 0)).catch((err) => logger$v.error("Failed to save settings:", err));
354
+ ).then(() => fs.promises.chmod(getSettingsPath(), 384).catch((err) => {
355
+ logger$x.warn("Failed to chmod settings file:", err);
356
+ })).catch((err) => logger$x.error("Failed to save settings:", err));
355
357
  }
356
358
  function saveSettings() {
357
359
  saveDirty = true;
@@ -530,7 +532,7 @@ const urlSafety = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePro
530
532
  }, Symbol.toStringTag, { value: "Module" }));
531
533
  const MAX_CUSTOM_HISTORY = 50;
532
534
  const READER_MODE_DATA_URL_PREFIX = "data:text/html;charset=utf-8,";
533
- const logger$u = createLogger("Tab");
535
+ const logger$w = createLogger("Tab");
534
536
  const sessionCertExceptions = /* @__PURE__ */ new WeakMap();
535
537
  const sessionsWithVerifyProc = /* @__PURE__ */ new WeakSet();
536
538
  const CERT_VERIFY_TRUST = 0;
@@ -596,7 +598,7 @@ class Tab {
596
598
  guardedLoadURL(url, options) {
597
599
  const blockReason = this.getNavigationBlockReason(url);
598
600
  if (blockReason) {
599
- logger$u.warn(blockReason);
601
+ logger$w.warn(blockReason);
600
602
  return blockReason;
601
603
  }
602
604
  void this.view.webContents.loadURL(url, options);
@@ -680,7 +682,7 @@ class Tab {
680
682
  wc.setWindowOpenHandler(({ url, disposition }) => {
681
683
  const error = this.getNavigationBlockReason(url);
682
684
  if (error) {
683
- logger$u.warn(error);
685
+ logger$w.warn(error);
684
686
  return { action: "deny" };
685
687
  }
686
688
  this.onOpenUrl?.({
@@ -694,7 +696,7 @@ class Tab {
694
696
  const error = this.getNavigationBlockReason(url);
695
697
  if (!error) return;
696
698
  event.preventDefault();
697
- logger$u.warn(`${context}: ${error}`);
699
+ logger$w.warn(`${context}: ${error}`);
698
700
  };
699
701
  wc.on("will-navigate", (event, url) => {
700
702
  blockNavigation(event, url, "Blocked top-level navigation");
@@ -778,7 +780,7 @@ class Tab {
778
780
  ::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.12); border-radius: 999px; }
779
781
  ::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.22); }
780
782
  ::-webkit-scrollbar-corner { background: transparent; }
781
- `).catch((err) => logger$u.warn("Failed to inject scrollbar CSS:", err));
783
+ `).catch((err) => logger$w.warn("Failed to inject scrollbar CSS:", err));
782
784
  });
783
785
  wc.on("page-favicon-updated", (_, favicons) => {
784
786
  this._state.favicon = favicons[0] || "";
@@ -814,7 +816,7 @@ class Tab {
814
816
  ).then((highlightedText) => {
815
817
  this.buildContextMenu(wc, params, highlightedText.trim());
816
818
  }).catch((err) => {
817
- logger$u.warn("Failed to inspect highlighted text for context menu:", err);
819
+ logger$w.warn("Failed to inspect highlighted text for context menu:", err);
818
820
  this.buildContextMenu(wc, params, "");
819
821
  });
820
822
  });
@@ -1015,7 +1017,7 @@ class Tab {
1015
1017
  "document.documentElement.outerHTML"
1016
1018
  );
1017
1019
  } catch (err) {
1018
- logger$u.warn("Failed to retrieve page source:", err);
1020
+ logger$w.warn("Failed to retrieve page source:", err);
1019
1021
  return;
1020
1022
  }
1021
1023
  const escaped = html.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
@@ -1135,7 +1137,9 @@ class Tab {
1135
1137
  range.insertNode(mark);
1136
1138
  }
1137
1139
  }
1138
- } catch(e) {}
1140
+ } catch {
1141
+ // Swallow — complex cross-node selections may fail to wrap
1142
+ }
1139
1143
  sel.removeAllRanges();
1140
1144
  // Notify main process for persistence
1141
1145
  window.__vessel.notifyHighlightSelection(text);
@@ -1143,7 +1147,7 @@ class Tab {
1143
1147
  document.addEventListener('mouseup', window.__vesselHighlightHandler);
1144
1148
  }
1145
1149
  })()
1146
- `).catch((err) => logger$u.warn("Failed to inject highlight listener:", err));
1150
+ `).catch((err) => logger$w.warn("Failed to inject highlight listener:", err));
1147
1151
  } else {
1148
1152
  void wc.executeJavaScript(`
1149
1153
  (function() {
@@ -1154,7 +1158,7 @@ class Tab {
1154
1158
  delete window.__vesselHighlightHandler;
1155
1159
  }
1156
1160
  })()
1157
- `).catch((err) => logger$u.warn("Failed to remove highlight listener:", err));
1161
+ `).catch((err) => logger$w.warn("Failed to remove highlight listener:", err));
1158
1162
  }
1159
1163
  }
1160
1164
  get webContentsId() {
@@ -1191,7 +1195,7 @@ const SEARCH_ENGINE_PRESETS = {
1191
1195
  ecosia: { label: "Ecosia", url: "https://www.ecosia.org/search?q=" },
1192
1196
  kagi: { label: "Kagi", url: "https://kagi.com/search?q=" }
1193
1197
  };
1194
- const logger$t = createLogger("JsonPersistence");
1198
+ const logger$v = createLogger("JsonPersistence");
1195
1199
  function canUseSafeStorage() {
1196
1200
  try {
1197
1201
  return electron.safeStorage.isEncryptionAvailable();
@@ -1256,7 +1260,9 @@ function createDebouncedJsonPersistence({
1256
1260
  data,
1257
1261
  typeof data === "string" ? { encoding: "utf-8", mode: 384 } : { mode: 384 }
1258
1262
  )
1259
- ).then(() => fs.promises.chmod(filePath2, 384).catch(() => void 0)).catch((err) => logger$t.error(`Failed to save ${logLabel}:`, err));
1263
+ ).then(() => fs.promises.chmod(filePath2, 384).catch((err) => {
1264
+ logger$v.warn(`Failed to chmod ${logLabel}:`, err);
1265
+ })).catch((err) => logger$v.error(`Failed to save ${logLabel}:`, err));
1260
1266
  };
1261
1267
  const schedule = () => {
1262
1268
  saveDirty2 = true;
@@ -2948,7 +2954,7 @@ function destroySession(tabId) {
2948
2954
  sessions.delete(tabId);
2949
2955
  }
2950
2956
  }
2951
- const logger$s = createLogger("TabManager");
2957
+ const logger$u = createLogger("TabManager");
2952
2958
  function sanitizeFilename(title, ext) {
2953
2959
  const clean = title.replace(/[<>:"/\\|?*\x00-\x1f]/g, " ").replace(/\s+/g, " ").trim();
2954
2960
  const escapedExt = ext.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -3367,7 +3373,7 @@ class TabManager {
3367
3373
  }));
3368
3374
  if (entries.length > 0) {
3369
3375
  void highlightBatchOnPage(wc, entries).catch(
3370
- (err) => logger$s.warn("Failed to batch highlight:", err)
3376
+ (err) => logger$u.warn("Failed to batch highlight:", err)
3371
3377
  );
3372
3378
  }
3373
3379
  }
@@ -3389,12 +3395,12 @@ class TabManager {
3389
3395
  const result = await captureSelectionHighlight(wc);
3390
3396
  if (result.success && result.text) {
3391
3397
  await highlightOnPage(wc, null, result.text, void 0, void 0, "yellow").catch(
3392
- (err) => logger$s.warn("Failed to capture highlight:", err)
3398
+ (err) => logger$u.warn("Failed to capture highlight:", err)
3393
3399
  );
3394
3400
  }
3395
3401
  this.highlightCaptureCallback?.(result);
3396
3402
  } catch (err) {
3397
- logger$s.warn("Failed to capture highlight from page:", err);
3403
+ logger$u.warn("Failed to capture highlight from page:", err);
3398
3404
  this.highlightCaptureCallback?.({
3399
3405
  success: false,
3400
3406
  message: "Could not capture selection"
@@ -3419,7 +3425,7 @@ class TabManager {
3419
3425
  void this.removeHighlightMarksForText(wc, text);
3420
3426
  }
3421
3427
  } catch (err) {
3422
- logger$s.warn("Failed to remove highlight from matching tab:", err);
3428
+ logger$u.warn("Failed to remove highlight from matching tab:", err);
3423
3429
  }
3424
3430
  }
3425
3431
  this.highlightCaptureCallback?.({
@@ -3450,12 +3456,12 @@ class TabManager {
3450
3456
  void 0,
3451
3457
  color
3452
3458
  ).catch(
3453
- (err) => logger$s.warn("Failed to update highlight color:", err)
3459
+ (err) => logger$u.warn("Failed to update highlight color:", err)
3454
3460
  );
3455
3461
  });
3456
3462
  }
3457
3463
  } catch (err) {
3458
- logger$s.warn("Failed to iterate highlights for color change:", err);
3464
+ logger$u.warn("Failed to iterate highlights for color change:", err);
3459
3465
  }
3460
3466
  }
3461
3467
  this.highlightCaptureCallback?.({
@@ -3510,7 +3516,7 @@ class TabManager {
3510
3516
  });
3511
3517
  })()`
3512
3518
  ).catch(
3513
- (err) => logger$s.warn("Failed to remove highlight marks:", err)
3519
+ (err) => logger$u.warn("Failed to remove highlight marks:", err)
3514
3520
  );
3515
3521
  }
3516
3522
  broadcastState(meta = { persistSession: false }) {
@@ -3532,9 +3538,6 @@ const AIChannels = {
3532
3538
  AI_STREAM_END: "ai:stream-end",
3533
3539
  AI_STREAM_IDLE: "ai:stream-idle",
3534
3540
  AI_RESEARCH_CLARIFICATION: "ai:research-clarification",
3535
- AUTOMATION_ACTIVITY_START: "automation:activity-start",
3536
- AUTOMATION_ACTIVITY_CHUNK: "automation:activity-chunk",
3537
- AUTOMATION_ACTIVITY_END: "automation:activity-end",
3538
3541
  AI_CANCEL: "ai:cancel",
3539
3542
  AI_FETCH_MODELS: "ai:fetch-models",
3540
3543
  AGENT_RUNTIME_GET: "agent-runtime:get",
@@ -3561,6 +3564,9 @@ const AutomationChannels = {
3561
3564
  AUTOMATION_GET_INSTALLED: "automation:get-installed",
3562
3565
  AUTOMATION_INSTALL_FROM_FILE: "automation:install-from-file",
3563
3566
  AUTOMATION_UNINSTALL: "automation:uninstall",
3567
+ AUTOMATION_ACTIVITY_START: "automation:activity-start",
3568
+ AUTOMATION_ACTIVITY_CHUNK: "automation:activity-chunk",
3569
+ AUTOMATION_ACTIVITY_END: "automation:activity-end",
3564
3570
  SCHEDULE_GET_ALL: "schedule:get-all",
3565
3571
  SCHEDULE_CREATE: "schedule:create",
3566
3572
  SCHEDULE_UPDATE: "schedule:update",
@@ -3646,6 +3652,9 @@ const HumanVaultChannels = {
3646
3652
  HUMAN_VAULT_REMOVE: "human-vault:remove",
3647
3653
  HUMAN_VAULT_AUDIT_LOG: "human-vault:audit-log"
3648
3654
  };
3655
+ const McpChannels = {
3656
+ MCP_REGENERATE_TOKEN: "mcp:regenerate-token"
3657
+ };
3649
3658
  const OpenRouterChannels = {
3650
3659
  OPENROUTER_START_AUTH: "openrouter:start-auth",
3651
3660
  OPENROUTER_CANCEL_AUTH: "openrouter:cancel-auth",
@@ -3695,8 +3704,9 @@ const SettingsChannels = {
3695
3704
  SETTINGS_SET: "settings:set",
3696
3705
  SETTINGS_UPDATE: "settings:update",
3697
3706
  SETTINGS_HEALTH_GET: "settings:health:get",
3698
- SETTINGS_HEALTH_UPDATE: "settings:health:update",
3699
- MCP_REGENERATE_TOKEN: "mcp:regenerate-token",
3707
+ SETTINGS_HEALTH_UPDATE: "settings:health:update"
3708
+ };
3709
+ const SupportChannels = {
3700
3710
  SUPPORT_SUBMIT_FEEDBACK: "support:submit-feedback"
3701
3711
  };
3702
3712
  const TabChannels = {
@@ -3728,14 +3738,7 @@ const TabChannels = {
3728
3738
  TAB_TOGGLE_MUTE: "tab:toggle-mute",
3729
3739
  TAB_PRINT: "tab:print",
3730
3740
  TAB_PRINT_TO_PDF: "tab:print-to-pdf",
3731
- TAB_TOGGLE_PIP: "tab:toggle-pip",
3732
- OPEN_NEW_WINDOW: "window:open-new",
3733
- OPEN_PRIVATE_WINDOW: "private:open-window",
3734
- IS_PRIVATE_MODE: "private:is-private",
3735
- FIND_IN_PAGE_START: "find:start",
3736
- FIND_IN_PAGE_NEXT: "find:next",
3737
- FIND_IN_PAGE_STOP: "find:stop",
3738
- FIND_IN_PAGE_RESULT: "find:result"
3741
+ TAB_TOGGLE_PIP: "tab:toggle-pip"
3739
3742
  };
3740
3743
  const UIChannels = {
3741
3744
  SIDEBAR_TOGGLE: "ui:sidebar-toggle",
@@ -3764,7 +3767,14 @@ const VaultChannels = {
3764
3767
  const WindowControlChannels = {
3765
3768
  WINDOW_MINIMIZE: "window:minimize",
3766
3769
  WINDOW_MAXIMIZE: "window:maximize",
3767
- WINDOW_CLOSE: "window:close"
3770
+ WINDOW_CLOSE: "window:close",
3771
+ OPEN_NEW_WINDOW: "window:open-new",
3772
+ OPEN_PRIVATE_WINDOW: "private:open-window",
3773
+ IS_PRIVATE_MODE: "private:is-private",
3774
+ FIND_IN_PAGE_START: "find:start",
3775
+ FIND_IN_PAGE_NEXT: "find:next",
3776
+ FIND_IN_PAGE_STOP: "find:stop",
3777
+ FIND_IN_PAGE_RESULT: "find:result"
3768
3778
  };
3769
3779
  const Channels = {
3770
3780
  ...AIChannels,
@@ -3779,6 +3789,7 @@ const Channels = {
3779
3789
  ...HighlightChannels,
3780
3790
  ...HistoryChannels,
3781
3791
  ...HumanVaultChannels,
3792
+ ...McpChannels,
3782
3793
  ...OpenRouterChannels,
3783
3794
  ...PermissionChannels,
3784
3795
  ...PremiumChannels,
@@ -3786,6 +3797,7 @@ const Channels = {
3786
3797
  ...SecurityChannels,
3787
3798
  ...SessionChannels,
3788
3799
  ...SettingsChannels,
3800
+ ...SupportChannels,
3789
3801
  ...TabChannels,
3790
3802
  ...UIChannels,
3791
3803
  ...UpdateChannels,
@@ -4748,7 +4760,15 @@ function errorResult(error, value) {
4748
4760
  function getErrorMessage(error, fallback = "Unknown error") {
4749
4761
  return error instanceof Error && error.message ? error.message : fallback;
4750
4762
  }
4751
- const logger$r = createLogger("Premium");
4763
+ async function readJsonResponse(response, fallback, onError) {
4764
+ try {
4765
+ return await response.json();
4766
+ } catch (err) {
4767
+ onError(getErrorMessage(err, "JSON parse failed"));
4768
+ return fallback;
4769
+ }
4770
+ }
4771
+ const logger$t = createLogger("Premium");
4752
4772
  const VERIFICATION_API = process.env.VESSEL_PREMIUM_API || "https://vesselpremium.quantaintellect.com";
4753
4773
  const FREE_TOOL_ITERATION_LIMIT = 50;
4754
4774
  const REVALIDATION_INTERVAL_MS = 24 * 60 * 60 * 1e3;
@@ -4924,7 +4944,7 @@ async function verifySubscription$1(identifier) {
4924
4944
  });
4925
4945
  if (!res.ok) {
4926
4946
  const detail = await readApiErrorDetail(res);
4927
- logger$r.warn(
4947
+ logger$t.warn(
4928
4948
  "Verification API returned a non-OK status:",
4929
4949
  res.status,
4930
4950
  detail
@@ -4943,7 +4963,7 @@ async function verifySubscription$1(identifier) {
4943
4963
  setSetting("premium", updated);
4944
4964
  return updated;
4945
4965
  } catch (err) {
4946
- logger$r.warn("Verification failed:", err);
4966
+ logger$t.warn("Verification failed:", err);
4947
4967
  return current;
4948
4968
  }
4949
4969
  }
@@ -4961,7 +4981,11 @@ async function requestActivationCode(email) {
4961
4981
  headers: { "Content-Type": "application/json" },
4962
4982
  body: JSON.stringify({ email: normalizedEmail })
4963
4983
  });
4964
- const data = await res.json().catch(() => ({}));
4984
+ const data = await readJsonResponse(
4985
+ res,
4986
+ {},
4987
+ (msg) => logger$t.warn("Failed to parse premium activation response:", msg)
4988
+ );
4965
4989
  if (!res.ok || !data.challengeToken) {
4966
4990
  return errorResult(data.error || `HTTP ${res.status}`);
4967
4991
  }
@@ -5002,7 +5026,11 @@ async function verifyActivationCode(email, code, challengeToken) {
5002
5026
  challengeToken: challengeToken.trim()
5003
5027
  })
5004
5028
  });
5005
- const data = await res.json().catch(() => ({}));
5029
+ const data = await readJsonResponse(
5030
+ res,
5031
+ {},
5032
+ (msg) => logger$t.warn("Failed to parse premium verification response:", msg)
5033
+ );
5006
5034
  if (!res.ok) {
5007
5035
  return errorResult(data.error || `HTTP ${res.status}`, {
5008
5036
  state: getPremiumState()
@@ -5598,7 +5626,7 @@ const EXTRACT_TIMEOUT_MAX_MS = 2e4;
5598
5626
  const MUTATION_CAPTURE_INTERVAL_MS = 5e3;
5599
5627
  const MUTATION_SETTLE_AFTER_MS = 1500;
5600
5628
  const AGENT_STREAM_IDLE_TIMEOUT_MS = 3e4;
5601
- const logger$q = createLogger("Extractor");
5629
+ const logger$s = createLogger("Extractor");
5602
5630
  const EXTRACTION_CACHE_TTL_MS = 1500;
5603
5631
  const MAX_EXTRACTION_CACHE_ENTRIES = 50;
5604
5632
  const extractionCache = new BoundedCache(
@@ -6363,9 +6391,9 @@ async function executeScript(webContents, script, options = {}) {
6363
6391
  const message = err instanceof Error ? err.message : String(err);
6364
6392
  const detail = `Failed to execute page script${label} on ${url}: ${message}`;
6365
6393
  if (options.warnOnFailure) {
6366
- logger$q.warn(detail);
6394
+ logger$s.warn(detail);
6367
6395
  } else {
6368
- logger$q.debug(detail);
6396
+ logger$s.debug(detail);
6369
6397
  }
6370
6398
  return null;
6371
6399
  } finally {
@@ -6474,7 +6502,7 @@ async function estimateExtractionTimeout(webContents) {
6474
6502
  return EXTRACT_TIMEOUT_BASE_MS + extra;
6475
6503
  }
6476
6504
  } catch (err) {
6477
- logger$q.warn("Failed to estimate extraction timeout, using base timeout:", err);
6505
+ logger$s.warn("Failed to estimate extraction timeout, using base timeout:", err);
6478
6506
  }
6479
6507
  return EXTRACT_TIMEOUT_BASE_MS;
6480
6508
  }
@@ -7442,7 +7470,7 @@ function isClickReadLoop(names) {
7442
7470
  return clickReadPairs >= 2;
7443
7471
  }
7444
7472
  const TERMINAL_TOOL_RESULT = "__VESSEL_TERMINAL_TOOL_RESULT__";
7445
- const logger$p = createLogger("PromptCache");
7473
+ const logger$r = createLogger("PromptCache");
7446
7474
  function shortHash(value) {
7447
7475
  return crypto$2.createHash("sha256").update(value).digest("hex").slice(0, 12);
7448
7476
  }
@@ -7494,7 +7522,7 @@ function logOpenAIPromptCacheUsage(usage, context) {
7494
7522
  const details = record.prompt_tokens_details;
7495
7523
  const cachedTokens = details && typeof details === "object" ? numericField(details, "cached_tokens") : null;
7496
7524
  if (promptTokens === null && cachedTokens === null) return;
7497
- logger$p.debug("OpenAI prompt cache usage", {
7525
+ logger$r.debug("OpenAI prompt cache usage", {
7498
7526
  model: context.model,
7499
7527
  mode: context.mode,
7500
7528
  promptTokens,
@@ -7510,7 +7538,7 @@ function logAnthropicPromptCacheUsage(usage, context) {
7510
7538
  if (inputTokens === null && cacheCreationTokens === null && cacheReadTokens === null) {
7511
7539
  return;
7512
7540
  }
7513
- logger$p.debug("Anthropic prompt cache usage", {
7541
+ logger$r.debug("Anthropic prompt cache usage", {
7514
7542
  model: context.model,
7515
7543
  mode: context.mode,
7516
7544
  inputTokens,
@@ -8403,7 +8431,7 @@ function recoverNarratedActionToolCalls(text, availableToolNames) {
8403
8431
  }
8404
8432
  return recovered;
8405
8433
  }
8406
- const logger$o = createLogger("OpenAIProvider");
8434
+ const logger$q = createLogger("OpenAIProvider");
8407
8435
  function shouldDebugAgentLoop() {
8408
8436
  const value = process.env.VESSEL_DEBUG_AGENT_LOOP;
8409
8437
  return value === "1" || value === "true";
@@ -8671,9 +8699,9 @@ function shouldRetryCompactToolLoop(profile, text, hasToolHistory, userMessage)
8671
8699
  function logAgentLoopDebug(payload) {
8672
8700
  if (!shouldDebugAgentLoop()) return;
8673
8701
  try {
8674
- logger$o.info(`[agent-debug] ${JSON.stringify(payload)}`);
8702
+ logger$q.info(`[agent-debug] ${JSON.stringify(payload)}`);
8675
8703
  } catch (err) {
8676
- logger$o.warn("Failed to serialize debug payload:", err);
8704
+ logger$q.warn("Failed to serialize debug payload:", err);
8677
8705
  }
8678
8706
  }
8679
8707
  function formatOpenAICompatErrorMessage(providerId, message) {
@@ -9297,7 +9325,7 @@ function createLocalPkceOAuthFlow(config) {
9297
9325
  isInProgress: () => activeFlow !== null
9298
9326
  };
9299
9327
  }
9300
- const logger$n = createLogger("CodexOAuth");
9328
+ const logger$p = createLogger("CodexOAuth");
9301
9329
  const ISSUER = "https://auth.openai.com";
9302
9330
  const CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
9303
9331
  const SCOPE = "openid profile email offline_access api.connectors.read api.connectors.invoke";
@@ -9428,7 +9456,7 @@ function escapeHtml$1(text) {
9428
9456
  }
9429
9457
  const codexOAuth = createLocalPkceOAuthFlow({
9430
9458
  name: "Codex",
9431
- logger: logger$n,
9459
+ logger: logger$p,
9432
9460
  preferredPorts: [PREFERRED_PORT$1, FALLBACK_PORT$1],
9433
9461
  timeoutMs: AUTH_TIMEOUT_MS$1,
9434
9462
  callbackPath: () => "/auth/callback",
@@ -9452,7 +9480,7 @@ async function startCodexOAuth(onStatus) {
9452
9480
  function cancelCodexOAuth() {
9453
9481
  codexOAuth.cancel();
9454
9482
  }
9455
- const logger$m = createLogger("CodexProvider");
9483
+ const logger$o = createLogger("CodexProvider");
9456
9484
  const REFRESH_WINDOW_MS = 5 * 60 * 1e3;
9457
9485
  const CODEX_BACKEND_BASE_URL = "https://chatgpt.com/backend-api/codex";
9458
9486
  const CODEX_CLIENT_VERSION = "0.129.0";
@@ -9517,7 +9545,7 @@ class CodexProvider {
9517
9545
  async ensureFreshTokens() {
9518
9546
  if (Date.now() < this.tokens.expiresAt - REFRESH_WINDOW_MS) return;
9519
9547
  try {
9520
- logger$m.info("Refreshing Codex access token");
9548
+ logger$o.info("Refreshing Codex access token");
9521
9549
  const fresh = await refreshAccessToken(this.tokens);
9522
9550
  this.tokens = fresh;
9523
9551
  writeStoredCodexTokens(fresh);
@@ -9665,7 +9693,7 @@ class CodexProvider {
9665
9693
  } catch (err) {
9666
9694
  if (err.name !== "AbortError") {
9667
9695
  const msg = err instanceof Error ? err.message : String(err);
9668
- logger$m.error("Codex streamQuery error:", err);
9696
+ logger$o.error("Codex streamQuery error:", err);
9669
9697
  onChunk(`
9670
9698
 
9671
9699
  [Error: ${msg}]`);
@@ -9733,7 +9761,7 @@ class CodexProvider {
9733
9761
  } catch (err) {
9734
9762
  if (err.name !== "AbortError") {
9735
9763
  const msg = err instanceof Error ? err.message : String(err);
9736
- logger$m.error("Codex streamAgentQuery error:", err);
9764
+ logger$o.error("Codex streamAgentQuery error:", err);
9737
9765
  onChunk(`
9738
9766
 
9739
9767
  [Error: ${msg}]`);
@@ -10967,7 +10995,7 @@ function normalizeBookmarkMetadataUpdate(input) {
10967
10995
  }
10968
10996
  return normalized;
10969
10997
  }
10970
- const logger$l = createLogger("BookmarkManager");
10998
+ const logger$n = createLogger("BookmarkManager");
10971
10999
  const UNSORTED_ID = "unsorted";
10972
11000
  const ARCHIVE_FOLDER_NAME = "Archive";
10973
11001
  const NETSCAPE_BOOKMARKS_DOCTYPE = "<!DOCTYPE NETSCAPE-Bookmark-file-1>";
@@ -11540,7 +11568,7 @@ function importBookmarksFromJson(content) {
11540
11568
  emit$2();
11541
11569
  }
11542
11570
  } catch (err) {
11543
- logger$l.warn("Failed to import bookmarks from JSON:", err);
11571
+ logger$n.warn("Failed to import bookmarks from JSON:", err);
11544
11572
  errors++;
11545
11573
  }
11546
11574
  return { imported, skipped, errors };
@@ -11945,6 +11973,7 @@ async function resolveSelector(wc, index, selector) {
11945
11973
  if (extractedSelector) return extractedSelector;
11946
11974
  return null;
11947
11975
  }
11976
+ const logger$m = createLogger("LinkValidation");
11948
11977
  const DEAD_STATUS_CODES = /* @__PURE__ */ new Set([404, 410, 451]);
11949
11978
  const HEAD_FALLBACK_STATUS_CODES = /* @__PURE__ */ new Set([400, 403, 404, 405, 406, 500, 501]);
11950
11979
  function isHttpUrl(value) {
@@ -11967,7 +11996,9 @@ async function requestUrl(url, method, timeoutMs) {
11967
11996
  "user-agent": "Vessel/0.1.0 (+https://github.com/unmodeled-tyler/vessel-browser)"
11968
11997
  }
11969
11998
  });
11970
- await response.body?.cancel().catch(() => void 0);
11999
+ await response.body?.cancel().catch((err) => {
12000
+ logger$m.debug("Failed to cancel response body:", err);
12001
+ });
11971
12002
  return response;
11972
12003
  } finally {
11973
12004
  clearTimeout(timer);
@@ -12030,7 +12061,7 @@ function formatDeadLinkMessage(label, result) {
12030
12061
  const status = result.statusCode ? `HTTP ${result.statusCode}` : "dead link";
12031
12062
  return `Skipped stale link "${label}" because ${destination} returned ${status}. Try a different link or URL instead.`;
12032
12063
  }
12033
- const logger$k = createLogger("Screenshot");
12064
+ const logger$l = createLogger("Screenshot");
12034
12065
  const SCREENSHOT_RETRY_COUNT = 3;
12035
12066
  const SCREENSHOT_RETRY_BASE_DELAY_MS = 120;
12036
12067
  async function captureScreenshot(wc) {
@@ -12052,7 +12083,7 @@ async function captureScreenshot(wc) {
12052
12083
  }
12053
12084
  }
12054
12085
  } catch (err) {
12055
- logger$k.debug(
12086
+ logger$l.debug(
12056
12087
  `capturePage attempt ${attempt + 1} failed; retrying if attempts remain.`,
12057
12088
  getErrorMessage(err)
12058
12089
  );
@@ -14529,7 +14560,7 @@ class TabMutex {
14529
14560
  return run;
14530
14561
  }
14531
14562
  }
14532
- const logger$j = createLogger("PageActions");
14563
+ const logger$k = createLogger("PageActions");
14533
14564
  const DEFAULT_PAGE_SCRIPT_TIMEOUT_MS = 1500;
14534
14565
  const PAGE_SCRIPT_TIMEOUT = /* @__PURE__ */ Symbol("page-script-timeout");
14535
14566
  function pageBusyError(action) {
@@ -14557,7 +14588,7 @@ async function executePageScript(wc, script, options) {
14557
14588
  return result;
14558
14589
  } catch (err) {
14559
14590
  const label = options?.label ? ` (${options.label})` : "";
14560
- logger$j.warn(`Failed to execute page script${label}:`, err);
14591
+ logger$k.warn(`Failed to execute page script${label}:`, err);
14561
14592
  return null;
14562
14593
  } finally {
14563
14594
  if (timer) {
@@ -14754,7 +14785,9 @@ Page title: ${title}` : "";
14754
14785
  signals.push('consent-banner:' + consentSelectors[i]);
14755
14786
  break;
14756
14787
  }
14757
- } catch(e) {}
14788
+ } catch {
14789
+ // Swallow — cross-origin frames may block selector access
14790
+ }
14758
14791
  }
14759
14792
  var vw = window.innerWidth || 0;
14760
14793
  var vh = window.innerHeight || 0;
@@ -14797,7 +14830,7 @@ Search results snapshot:
14797
14830
  ${truncated}`;
14798
14831
  }
14799
14832
  } catch (err) {
14800
- logger$j.warn("Failed to build post-search summary, falling back to nav summary:", err);
14833
+ logger$k.warn("Failed to build post-search summary, falling back to nav summary:", err);
14801
14834
  }
14802
14835
  const fallback = await getPostNavSummary(wc);
14803
14836
  return fallback ? `${fallback}
@@ -14820,7 +14853,7 @@ Page snapshot after navigation:
14820
14853
  ${truncated}`;
14821
14854
  }
14822
14855
  } catch (err) {
14823
- logger$j.warn("Failed to build post-click navigation summary:", err);
14856
+ logger$k.warn("Failed to build post-click navigation summary:", err);
14824
14857
  }
14825
14858
  return "";
14826
14859
  }
@@ -15710,7 +15743,7 @@ async function restoreLocaleSnapshot(wc, snapshot2) {
15710
15743
  }
15711
15744
  }
15712
15745
  } catch (err) {
15713
- logger$j.warn("Failed to restore locale via history navigation, trying URL reload fallback:", err);
15746
+ logger$k.warn("Failed to restore locale via history navigation, trying URL reload fallback:", err);
15714
15747
  }
15715
15748
  if (snapshot2.url && snapshot2.url !== wc.getURL()) {
15716
15749
  try {
@@ -15719,7 +15752,7 @@ async function restoreLocaleSnapshot(wc, snapshot2) {
15719
15752
  await waitForLoad(wc, 3e3);
15720
15753
  return;
15721
15754
  } catch (err) {
15722
- logger$j.warn("Failed to restore locale via safe URL load, trying page reload fallback:", err);
15755
+ logger$k.warn("Failed to restore locale via safe URL load, trying page reload fallback:", err);
15723
15756
  }
15724
15757
  }
15725
15758
  if (snapshot2.url) {
@@ -15727,7 +15760,7 @@ async function restoreLocaleSnapshot(wc, snapshot2) {
15727
15760
  await wc.reload();
15728
15761
  await waitForLoad(wc, 3e3);
15729
15762
  } catch (err) {
15730
- logger$j.warn("Failed to restore locale via page reload:", err);
15763
+ logger$k.warn("Failed to restore locale via page reload:", err);
15731
15764
  }
15732
15765
  }
15733
15766
  }
@@ -15792,7 +15825,7 @@ async function followHrefFromClickResult(wc, beforeUrl, result, logMessage) {
15792
15825
  const hrefUrl = wc.getURL();
15793
15826
  if (hrefUrl !== beforeUrl) return `${result.split("\n")[0]} -> ${hrefUrl}`;
15794
15827
  } catch (err) {
15795
- logger$j.warn(logMessage, err);
15828
+ logger$k.warn(logMessage, err);
15796
15829
  }
15797
15830
  return null;
15798
15831
  }
@@ -16004,7 +16037,7 @@ ${postActivationOverlayHint}`;
16004
16037
  return `${clickText} -> ${hrefFallbackUrl} (recovered via href fallback)`;
16005
16038
  }
16006
16039
  } catch (err) {
16007
- logger$j.warn("Failed href fallback after click, returning generic click result:", err);
16040
+ logger$k.warn("Failed href fallback after click, returning generic click result:", err);
16008
16041
  }
16009
16042
  }
16010
16043
  }
@@ -16049,7 +16082,7 @@ async function tryAutoDismissCartDialog(wc) {
16049
16082
  return result;
16050
16083
  }
16051
16084
  } catch (err) {
16052
- logger$j.warn("Failed to auto-dismiss cart dialog, falling back to dialog actions:", err);
16085
+ logger$k.warn("Failed to auto-dismiss cart dialog, falling back to dialog actions:", err);
16053
16086
  }
16054
16087
  return null;
16055
16088
  }
@@ -16502,7 +16535,9 @@ async function tryDismissConsentIframe(wc) {
16502
16535
  return 'Clicked iframe consent button: ' + text.slice(0, 60);
16503
16536
  }
16504
16537
  }
16505
- } catch(e) {}
16538
+ } catch {
16539
+ // Swallow — selector may be invalid or cross-origin frame may block access
16540
+ }
16506
16541
  }
16507
16542
  // Text-match fallback on all buttons
16508
16543
  var buttons = document.querySelectorAll('button, [role="button"], a.message-component');
@@ -18204,7 +18239,7 @@ async function executeAction(name, args, ctx) {
18204
18239
  )
18205
18240
  ]);
18206
18241
  } catch (err) {
18207
- logger$j.warn("Failed to extract content for read_page, falling back to lighter recovery:", err);
18242
+ logger$k.warn("Failed to extract content for read_page, falling back to lighter recovery:", err);
18208
18243
  content = null;
18209
18244
  }
18210
18245
  if (!content || content.content.length === 0) {
@@ -18221,12 +18256,12 @@ async function executeAction(name, args, ctx) {
18221
18256
  new Promise((resolve) => setTimeout(() => resolve(null), 3e3))
18222
18257
  ]);
18223
18258
  } catch (err) {
18224
- logger$j.warn("Failed to re-extract content after iframe consent dismissal:", err);
18259
+ logger$k.warn("Failed to re-extract content after iframe consent dismissal:", err);
18225
18260
  content = null;
18226
18261
  }
18227
18262
  }
18228
18263
  } catch (err) {
18229
- logger$j.warn("Failed iframe consent dismissal during read_page recovery:", err);
18264
+ logger$k.warn("Failed iframe consent dismissal during read_page recovery:", err);
18230
18265
  }
18231
18266
  }
18232
18267
  if (content && content.content.length > 0) {
@@ -18639,7 +18674,7 @@ ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`
18639
18674
  try {
18640
18675
  page = await extractContent(wc);
18641
18676
  } catch (err) {
18642
- logger$j.warn("Failed to extract content for suggest:", err);
18677
+ logger$k.warn("Failed to extract content for suggest:", err);
18643
18678
  return "Could not read page. Try navigate to a working URL.";
18644
18679
  }
18645
18680
  const suggestions = [];
@@ -19027,7 +19062,7 @@ WARNING: You have clicked ${clickStreakCount} elements on this page without veri
19027
19062
  }
19028
19063
  return formattedResult + await getPostActionState$1(ctx, name) + clickNavSummary + streakWarning + flowCtx;
19029
19064
  }
19030
- const logger$i = createLogger("ResearchOrchestrator");
19065
+ const logger$j = createLogger("ResearchOrchestrator");
19031
19066
  const MAX_THREADS = 5;
19032
19067
  const MAX_TRACE_ARGS_CHARS = 1200;
19033
19068
  const MAX_TRACE_RESULT_CHARS = 2e3;
@@ -19216,7 +19251,7 @@ class ResearchOrchestrator {
19216
19251
  }
19217
19252
  stopAndSynthesizeCurrentFindings() {
19218
19253
  if (this.state.phase !== "executing") {
19219
- logger$i.warn("Not executing, ignoring stopAndSynthesizeCurrentFindings");
19254
+ logger$j.warn("Not executing, ignoring stopAndSynthesizeCurrentFindings");
19220
19255
  return;
19221
19256
  }
19222
19257
  this.stopRequested = true;
@@ -19250,23 +19285,23 @@ class ResearchOrchestrator {
19250
19285
  async startBrief(userQuery) {
19251
19286
  const query = userQuery.trim();
19252
19287
  if (!query) {
19253
- logger$i.warn("Ignoring empty Research Desk query");
19288
+ logger$j.warn("Ignoring empty Research Desk query");
19254
19289
  return;
19255
19290
  }
19256
19291
  if (this.state.phase !== "idle") {
19257
- logger$i.warn("Research already in progress, ignoring startBrief");
19292
+ logger$j.warn("Research already in progress, ignoring startBrief");
19258
19293
  return;
19259
19294
  }
19260
19295
  this.state = this.initialState();
19261
19296
  this.state.originalQuery = query;
19262
19297
  this.state.startedAt = (/* @__PURE__ */ new Date()).toISOString();
19263
19298
  this.setPhase("briefing");
19264
- logger$i.info(`Brief started for query: ${query.slice(0, 120)}`);
19299
+ logger$j.info(`Brief started for query: ${query.slice(0, 120)}`);
19265
19300
  }
19266
19301
  // ── phase: briefing → planning ─────────────────────────────────
19267
19302
  confirmBrief() {
19268
19303
  if (this.state.phase !== "briefing") {
19269
- logger$i.warn("Not in briefing phase, ignoring confirmBrief");
19304
+ logger$j.warn("Not in briefing phase, ignoring confirmBrief");
19270
19305
  return;
19271
19306
  }
19272
19307
  this.setPhase("planning");
@@ -19274,7 +19309,7 @@ class ResearchOrchestrator {
19274
19309
  // ── phase: planning → awaiting_approval ────────────────────────
19275
19310
  setObjectives(objectives) {
19276
19311
  if (this.state.phase !== "planning") {
19277
- logger$i.warn("Not in planning phase, ignoring setObjectives");
19312
+ logger$j.warn("Not in planning phase, ignoring setObjectives");
19278
19313
  return;
19279
19314
  }
19280
19315
  const threads = objectives.threads.slice(0, MAX_THREADS).map(mergeBlockedSourceDomains);
@@ -19303,11 +19338,11 @@ class ResearchOrchestrator {
19303
19338
  try {
19304
19339
  const parsed = JSON.parse(json);
19305
19340
  if (typeof parsed.researchQuestion !== "string" || !parsed.researchQuestion.trim()) {
19306
- logger$i.warn("Missing researchQuestion in objectives JSON");
19341
+ logger$j.warn("Missing researchQuestion in objectives JSON");
19307
19342
  return false;
19308
19343
  }
19309
19344
  if (!Array.isArray(parsed.threads) || parsed.threads.length === 0) {
19310
- logger$i.warn("Missing or empty threads array in objectives JSON");
19345
+ logger$j.warn("Missing or empty threads array in objectives JSON");
19311
19346
  return false;
19312
19347
  }
19313
19348
  const threads = parsed.threads.map((t, i) => {
@@ -19325,7 +19360,7 @@ class ResearchOrchestrator {
19325
19360
  };
19326
19361
  }).filter((thread) => thread.question && thread.searchQueries.length > 0).slice(0, MAX_THREADS);
19327
19362
  if (threads.length === 0) {
19328
- logger$i.warn("Objectives JSON did not contain any valid research threads");
19363
+ logger$j.warn("Objectives JSON did not contain any valid research threads");
19329
19364
  return false;
19330
19365
  }
19331
19366
  const objectives = {
@@ -19336,17 +19371,17 @@ class ResearchOrchestrator {
19336
19371
  totalSourceBudget: threads.reduce((sum, t) => sum + t.sourceBudget, 0)
19337
19372
  };
19338
19373
  this.setObjectives(objectives);
19339
- logger$i.info(`Parsed ${objectives.threads.length} threads from objectives`);
19374
+ logger$j.info(`Parsed ${objectives.threads.length} threads from objectives`);
19340
19375
  return true;
19341
19376
  } catch (err) {
19342
- logger$i.warn("Failed to parse objectives JSON", err);
19377
+ logger$j.warn("Failed to parse objectives JSON", err);
19343
19378
  return false;
19344
19379
  }
19345
19380
  }
19346
19381
  // ── phase: awaiting_approval → executing ───────────────────────
19347
19382
  approveObjectives(mode, includeTraces) {
19348
19383
  if (this.state.phase !== "awaiting_approval") {
19349
- logger$i.warn("Not awaiting approval, ignoring approveObjectives");
19384
+ logger$j.warn("Not awaiting approval, ignoring approveObjectives");
19350
19385
  return;
19351
19386
  }
19352
19387
  if (mode) this.state.supervisionMode = mode;
@@ -19381,7 +19416,7 @@ class ResearchOrchestrator {
19381
19416
  this.state.threads.map((thread) => {
19382
19417
  if (this.state.phase !== "executing") return null;
19383
19418
  return this.runSubAgent(thread, tabMutex).catch((err) => {
19384
- logger$i.error(`Sub-agent "${thread.label}" failed`, err);
19419
+ logger$j.error(`Sub-agent "${thread.label}" failed`, err);
19385
19420
  return {
19386
19421
  threadLabel: thread.label,
19387
19422
  threadQuestion: thread.question,
@@ -19410,7 +19445,7 @@ class ResearchOrchestrator {
19410
19445
  try {
19411
19446
  await this.synthesizeReport();
19412
19447
  } catch (err) {
19413
- logger$i.error("Auto-synthesis failed", err);
19448
+ logger$j.error("Auto-synthesis failed", err);
19414
19449
  this.state.error = `Synthesis failed: ${String(err)}`;
19415
19450
  this.setPhase("delivered");
19416
19451
  }
@@ -19521,7 +19556,7 @@ Start by searching for: ${thread.searchQueries.join(" or ")}`;
19521
19556
  try {
19522
19557
  this.tabManager.closeTab(tabId);
19523
19558
  } catch (err) {
19524
- logger$i.warn(`Failed to close sub-agent tab ${tabId}`, err);
19559
+ logger$j.warn(`Failed to close sub-agent tab ${tabId}`, err);
19525
19560
  }
19526
19561
  }
19527
19562
  }
@@ -19530,7 +19565,7 @@ Start by searching for: ${thread.searchQueries.join(" or ")}`;
19530
19565
  try {
19531
19566
  claims = await this.extractClaimsFromTranscript(thread, transcript);
19532
19567
  } catch (err) {
19533
- logger$i.warn(`Claim extraction failed for "${thread.label}"`, err);
19568
+ logger$j.warn(`Claim extraction failed for "${thread.label}"`, err);
19534
19569
  }
19535
19570
  }
19536
19571
  if (this.state.phase === "executing" && this.state.includeTraces) {
@@ -19620,7 +19655,7 @@ ${transcript.slice(0, 32e3)}`;
19620
19655
  (claim) => claim.claim && claim.sourceUrl && claim.extractedQuote
19621
19656
  );
19622
19657
  } catch {
19623
- logger$i.warn(`Failed to parse claims JSON for "${thread.label}"`);
19658
+ logger$j.warn(`Failed to parse claims JSON for "${thread.label}"`);
19624
19659
  return [];
19625
19660
  }
19626
19661
  }
@@ -19705,7 +19740,7 @@ ${transcript.slice(0, 32e3)}`;
19705
19740
  objectives
19706
19741
  };
19707
19742
  } catch (err) {
19708
- logger$i.warn("Failed to parse synthesis JSON, using sourced fallback report", err);
19743
+ logger$j.warn("Failed to parse synthesis JSON, using sourced fallback report", err);
19709
19744
  return buildFallbackReport(objectives, findings, String(err));
19710
19745
  }
19711
19746
  }
@@ -20252,7 +20287,7 @@ function loadRenderers(chromeView, sidebarView, devtoolsPanelView) {
20252
20287
  });
20253
20288
  }
20254
20289
  }
20255
- const logger$h = createLogger("PrivateWindow");
20290
+ const logger$i = createLogger("PrivateWindow");
20256
20291
  const privateWindows = /* @__PURE__ */ new Set();
20257
20292
  function layoutPrivateViews(state2) {
20258
20293
  const { window: win, chromeView, tabManager } = state2;
@@ -20473,7 +20508,7 @@ function createPrivateWindow() {
20473
20508
  privateSession.clearStorageData(),
20474
20509
  privateSession.clearCache()
20475
20510
  ]).catch((error) => {
20476
- logger$h.warn("Failed to clear private browsing session:", error);
20511
+ logger$i.warn("Failed to clear private browsing session:", error);
20477
20512
  });
20478
20513
  });
20479
20514
  privateWindows.add(state2);
@@ -20483,7 +20518,7 @@ function createPrivateWindow() {
20483
20518
  });
20484
20519
  loadPrivateRenderer(chromeView);
20485
20520
  win.show();
20486
- logger$h.info("Private browsing window opened");
20521
+ logger$i.info("Private browsing window opened");
20487
20522
  return state2;
20488
20523
  }
20489
20524
  const window$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
@@ -20857,7 +20892,7 @@ function registerTabHandlers(windowState2, _sendToRendererViews) {
20857
20892
  });
20858
20893
  }
20859
20894
  const require$1 = node_module.createRequire(require("url").pathToFileURL(__filename).href);
20860
- const logger$g = createLogger("DevTrace");
20895
+ const logger$h = createLogger("DevTrace");
20861
20896
  let cachedFactory;
20862
20897
  function createNoopTraceSession() {
20863
20898
  return {
@@ -20890,7 +20925,7 @@ function loadLocalFactory() {
20890
20925
  return cachedFactory;
20891
20926
  }
20892
20927
  } catch (err) {
20893
- logger$g.warn("Failed to load local trace logger:", err);
20928
+ logger$h.warn("Failed to load local trace logger:", err);
20894
20929
  }
20895
20930
  }
20896
20931
  return cachedFactory;
@@ -21721,7 +21756,7 @@ function registerContentHandlers(windowState2) {
21721
21756
  return windowState2.uiState.focusMode;
21722
21757
  });
21723
21758
  }
21724
- const logger$f = createLogger("HighlightIPC");
21759
+ const logger$g = createLogger("HighlightIPC");
21725
21760
  function registerHighlightHandlers(windowState2, sendToRendererViews) {
21726
21761
  const { tabManager, chromeView } = windowState2;
21727
21762
  const getActiveHighlightCountSafe = async () => {
@@ -21730,7 +21765,7 @@ function registerHighlightHandlers(windowState2, sendToRendererViews) {
21730
21765
  try {
21731
21766
  return await getHighlightCount(info.wc) ?? 0;
21732
21767
  } catch (err) {
21733
- logger$f.warn("Failed to get active highlight count:", err);
21768
+ logger$g.warn("Failed to get active highlight count:", err);
21734
21769
  return 0;
21735
21770
  }
21736
21771
  };
@@ -21755,13 +21790,13 @@ function registerHighlightHandlers(windowState2, sendToRendererViews) {
21755
21790
  const result = await captureSelectionHighlight(wc);
21756
21791
  if (result.success && result.text) {
21757
21792
  await highlightOnPage(wc, null, result.text, void 0, void 0, "yellow").catch(
21758
- (err) => logger$f.warn("Failed to highlight captured selection:", err)
21793
+ (err) => logger$g.warn("Failed to highlight captured selection:", err)
21759
21794
  );
21760
21795
  await emitHighlightCount();
21761
21796
  }
21762
21797
  return result;
21763
21798
  } catch (err) {
21764
- logger$f.warn("Failed to capture highlight from active tab:", err);
21799
+ logger$g.warn("Failed to capture highlight from active tab:", err);
21765
21800
  return { success: false, message: "Could not capture selection" };
21766
21801
  }
21767
21802
  });
@@ -21778,7 +21813,7 @@ function registerHighlightHandlers(windowState2, sendToRendererViews) {
21778
21813
  }
21779
21814
  });
21780
21815
  } catch (err) {
21781
- logger$f.warn("Failed to persist auto-highlight selection:", err);
21816
+ logger$g.warn("Failed to persist auto-highlight selection:", err);
21782
21817
  }
21783
21818
  });
21784
21819
  electron.ipcMain.handle(Channels.HIGHLIGHT_NAV_COUNT, (event) => {
@@ -21792,7 +21827,7 @@ function registerHighlightHandlers(windowState2, sendToRendererViews) {
21792
21827
  try {
21793
21828
  return scrollToHighlight(info.wc, index);
21794
21829
  } catch (err) {
21795
- logger$f.warn("Failed to scroll to highlight:", err);
21830
+ logger$g.warn("Failed to scroll to highlight:", err);
21796
21831
  return false;
21797
21832
  }
21798
21833
  });
@@ -21807,7 +21842,7 @@ function registerHighlightHandlers(windowState2, sendToRendererViews) {
21807
21842
  }
21808
21843
  return removed;
21809
21844
  } catch (err) {
21810
- logger$f.warn("Failed to remove highlight at index:", err);
21845
+ logger$g.warn("Failed to remove highlight at index:", err);
21811
21846
  return false;
21812
21847
  }
21813
21848
  });
@@ -21822,7 +21857,7 @@ function registerHighlightHandlers(windowState2, sendToRendererViews) {
21822
21857
  }
21823
21858
  return cleared;
21824
21859
  } catch (err) {
21825
- logger$f.warn("Failed to clear highlight elements:", err);
21860
+ logger$g.warn("Failed to clear highlight elements:", err);
21826
21861
  return false;
21827
21862
  }
21828
21863
  });
@@ -22791,7 +22826,7 @@ Exception: ${result.exceptionDetails}`);
22791
22826
  }
22792
22827
  );
22793
22828
  }
22794
- const logger$e = createLogger("MCP");
22829
+ const logger$f = createLogger("MCP");
22795
22830
  function asTextResponse(text) {
22796
22831
  return { content: [{ type: "text", text }] };
22797
22832
  }
@@ -22892,7 +22927,7 @@ async function getPostActionState(tabManager, name) {
22892
22927
  }
22893
22928
  }
22894
22929
  } catch (err) {
22895
- logger$e.warn("Failed to compute post-action state warning:", err);
22930
+ logger$f.warn("Failed to compute post-action state warning:", err);
22896
22931
  }
22897
22932
  return `${warning}
22898
22933
  [state: url=${wc.getURL()}, canGoBack=${tab.canGoBack()}, canGoForward=${tab.canGoForward()}, loading=${wc.isLoading()}]`;
@@ -22997,7 +23032,7 @@ async function waitForConditionMcp(wc, text, selector, timeoutMs) {
22997
23032
  }
22998
23033
  })()
22999
23034
  `).catch((err) => {
23000
- logger$e.warn("Failed to gather wait_for timeout diagnostic:", err);
23035
+ logger$f.warn("Failed to gather wait_for timeout diagnostic:", err);
23001
23036
  return null;
23002
23037
  });
23003
23038
  if (typeof diagnostic === "string" && diagnostic.trim()) {
@@ -23713,7 +23748,7 @@ function registerSessionTools(server, tabManager, runtime2) {
23713
23748
  )
23714
23749
  );
23715
23750
  }
23716
- const logger$d = createLogger("VaultShared");
23751
+ const logger$e = createLogger("VaultShared");
23717
23752
  const ALGORITHM = "aes-256-gcm";
23718
23753
  const IV_LENGTH = 12;
23719
23754
  const AUTH_TAG_LENGTH = 16;
@@ -23807,7 +23842,7 @@ function createVaultIO(vaultFilename, encrypt2, decrypt2) {
23807
23842
  cachedEntries = JSON.parse(json);
23808
23843
  return cachedEntries;
23809
23844
  } catch (err) {
23810
- logger$d.error("Failed to load vault:", err);
23845
+ logger$e.error("Failed to load vault:", err);
23811
23846
  throw new Error("Could not unlock the vault. Check OS secret storage availability.");
23812
23847
  }
23813
23848
  }
@@ -23890,7 +23925,7 @@ function createAuditLog(filename, maxEntries) {
23890
23925
  } catch {
23891
23926
  }
23892
23927
  } catch (err) {
23893
- logger$d.error("Failed to write audit log:", err);
23928
+ logger$e.error("Failed to write audit log:", err);
23894
23929
  }
23895
23930
  }
23896
23931
  function readAuditLog2(limit = 100) {
@@ -23900,7 +23935,7 @@ function createAuditLog(filename, maxEntries) {
23900
23935
  const lines = fs$1.readFileSync(auditPath, "utf-8").split("\n").filter((l) => l.trim());
23901
23936
  return lines.slice(-Math.min(limit, maxEntries)).map((line) => JSON.parse(line)).reverse();
23902
23937
  } catch (err) {
23903
- logger$d.error("Failed to read audit log:", err);
23938
+ logger$e.error("Failed to read audit log:", err);
23904
23939
  return [];
23905
23940
  }
23906
23941
  }
@@ -24004,7 +24039,7 @@ async function requestConsent(request) {
24004
24039
  }
24005
24040
  const AUDIT_FILENAME = "vessel-vault-audit.jsonl";
24006
24041
  const MAX_ENTRIES = 1e3;
24007
- const logger$c = createLogger("VaultAudit");
24042
+ const logger$d = createLogger("VaultAudit");
24008
24043
  function getAuditPath() {
24009
24044
  return path$1.join(electron.app.getPath("userData"), AUDIT_FILENAME);
24010
24045
  }
@@ -24018,7 +24053,7 @@ function appendAuditEntry(entry) {
24018
24053
  });
24019
24054
  fs$1.chmodSync(auditPath, 384);
24020
24055
  } catch (err) {
24021
- logger$c.error("Failed to write audit log:", err);
24056
+ logger$d.error("Failed to write audit log:", err);
24022
24057
  }
24023
24058
  }
24024
24059
  function readAuditLog$1(limit = 100) {
@@ -24028,7 +24063,7 @@ function readAuditLog$1(limit = 100) {
24028
24063
  const lines = fs$1.readFileSync(auditPath, "utf-8").split("\n").filter((l) => l.trim());
24029
24064
  return lines.slice(-Math.min(limit, MAX_ENTRIES)).map((line) => JSON.parse(line)).reverse();
24030
24065
  } catch (err) {
24031
- logger$c.error("Failed to read audit log:", err);
24066
+ logger$d.error("Failed to read audit log:", err);
24032
24067
  return [];
24033
24068
  }
24034
24069
  }
@@ -24198,7 +24233,7 @@ const mcpRuntimeState = {
24198
24233
  httpServer: null,
24199
24234
  authToken: null
24200
24235
  };
24201
- const logger$b = createLogger("MCP");
24236
+ const logger$c = createLogger("MCP");
24202
24237
  const MCP_AUTH_FILENAME = "mcp-auth.json";
24203
24238
  function getMcpAuthFilePath() {
24204
24239
  const configDir = process.env.VESSEL_CONFIG_DIR || path$1.join(
@@ -24235,7 +24270,7 @@ function writeMcpAuthFile(endpoint, token) {
24235
24270
  );
24236
24271
  fs$1.chmodSync(filePath2, 384);
24237
24272
  } catch (err) {
24238
- logger$b.warn("Failed to write auth file:", err);
24273
+ logger$c.warn("Failed to write auth file:", err);
24239
24274
  }
24240
24275
  }
24241
24276
  function clearMcpAuthFile() {
@@ -24261,7 +24296,7 @@ function clearMcpAuthFile() {
24261
24296
  );
24262
24297
  fs$1.chmodSync(filePath2, 384);
24263
24298
  } catch (err) {
24264
- logger$b.warn("Failed to clear auth file:", err);
24299
+ logger$c.warn("Failed to clear auth file:", err);
24265
24300
  }
24266
24301
  }
24267
24302
  function regenerateMcpAuthToken() {
@@ -24271,7 +24306,7 @@ function regenerateMcpAuthToken() {
24271
24306
  writeMcpAuthFile(endpoint, mcpRuntimeState.authToken);
24272
24307
  return { endpoint };
24273
24308
  }
24274
- const logger$a = createLogger("MCP");
24309
+ const logger$b = createLogger("MCP");
24275
24310
  function registerTools(server, tabManager, runtime2) {
24276
24311
  server.registerPrompt(
24277
24312
  "vessel-supervisor-brief",
@@ -24350,7 +24385,7 @@ function registerTools(server, tabManager, runtime2) {
24350
24385
  const page = await extractContent$1(wc);
24351
24386
  pageType = detectPageType(page);
24352
24387
  } catch (err) {
24353
- logger$a.warn("Failed to detect page type for tool scoring, falling back to GENERAL:", err);
24388
+ logger$b.warn("Failed to detect page type for tool scoring, falling back to GENERAL:", err);
24354
24389
  }
24355
24390
  }
24356
24391
  const scored = TOOL_DEFINITIONS.map((def) => {
@@ -25638,7 +25673,7 @@ ${JSON.stringify(otherHighlights, null, 2)}`
25638
25673
  void 0,
25639
25674
  h.color
25640
25675
  ).catch(
25641
- (err) => logger$a.warn("Failed to restore highlight after removal:", err)
25676
+ (err) => logger$b.warn("Failed to restore highlight after removal:", err)
25642
25677
  );
25643
25678
  }
25644
25679
  }
@@ -25905,7 +25940,7 @@ ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`
25905
25940
  try {
25906
25941
  page = await extractContent$1(wc);
25907
25942
  } catch (err) {
25908
- logger$a.warn("Failed to extract page while generating suggestions:", err);
25943
+ logger$b.warn("Failed to extract page while generating suggestions:", err);
25909
25944
  return asTextResponse(
25910
25945
  "Could not read page. Try navigate to a working URL."
25911
25946
  );
@@ -26515,7 +26550,7 @@ ${JSON.stringify(tableJson, null, 2)}`;
26515
26550
  try {
26516
26551
  targetDomain = new URL(tab.state.url).hostname;
26517
26552
  } catch (err) {
26518
- logger$a.warn("Failed to parse active tab URL for vault_status:", err);
26553
+ logger$b.warn("Failed to parse active tab URL for vault_status:", err);
26519
26554
  return asErrorTextResponse("Could not parse active tab URL");
26520
26555
  }
26521
26556
  }
@@ -26583,7 +26618,7 @@ Use vault_login to fill the login form. Credentials are filled directly — you
26583
26618
  try {
26584
26619
  hostname = new URL(tab.state.url).hostname;
26585
26620
  } catch (err) {
26586
- logger$a.warn("Failed to parse active tab URL for vault_login:", err);
26621
+ logger$b.warn("Failed to parse active tab URL for vault_login:", err);
26587
26622
  return asErrorTextResponse("Could not parse active tab URL");
26588
26623
  }
26589
26624
  const matches = findEntriesForDomain(`https://${hostname}`);
@@ -26679,7 +26714,7 @@ Use vault_login to fill the login form. Credentials are filled directly — you
26679
26714
  try {
26680
26715
  hostname = new URL(tab.state.url).hostname;
26681
26716
  } catch (err) {
26682
- logger$a.warn("Failed to parse active tab URL for vault_totp:", err);
26717
+ logger$b.warn("Failed to parse active tab URL for vault_totp:", err);
26683
26718
  return asErrorTextResponse("Could not parse active tab URL");
26684
26719
  }
26685
26720
  const matches = findEntriesForDomain(`https://${hostname}`);
@@ -27027,7 +27062,7 @@ function startMcpServer(tabManager, runtime2, port) {
27027
27062
  await mcpServer.connect(transport);
27028
27063
  await transport.handleRequest(req, res);
27029
27064
  } catch (error) {
27030
- logger$a.error("Error handling request:", error);
27065
+ logger$b.error("Error handling request:", error);
27031
27066
  if (!res.headersSent) {
27032
27067
  res.writeHead(500, { "Content-Type": "application/json" });
27033
27068
  res.end(
@@ -27046,7 +27081,7 @@ function startMcpServer(tabManager, runtime2, port) {
27046
27081
  };
27047
27082
  server.once("error", (error) => {
27048
27083
  const message = error.code === "EADDRINUSE" ? `Port ${port} is already in use. MCP server not started.` : error.message;
27049
- logger$a.error("Server error:", error);
27084
+ logger$b.error("Server error:", error);
27050
27085
  clearMcpAuthFile();
27051
27086
  setMcpHealth({
27052
27087
  configuredPort: port,
@@ -27078,7 +27113,7 @@ function startMcpServer(tabManager, runtime2, port) {
27078
27113
  message: `MCP server listening on ${endpoint}.`
27079
27114
  });
27080
27115
  if (process.env.VESSEL_DEBUG_MCP === "1" || process.env.VESSEL_DEBUG_MCP === "true") {
27081
- logger$a.info(`Server listening on ${endpoint} (auth enabled)`);
27116
+ logger$b.info(`Server listening on ${endpoint} (auth enabled)`);
27082
27117
  }
27083
27118
  if (mcpRuntimeState.authToken) {
27084
27119
  writeMcpAuthFile(endpoint, mcpRuntimeState.authToken);
@@ -27117,12 +27152,13 @@ function stopMcpServer() {
27117
27152
  message: "MCP server is stopped."
27118
27153
  });
27119
27154
  if (process.env.VESSEL_DEBUG_MCP === "1" || process.env.VESSEL_DEBUG_MCP === "true") {
27120
- logger$a.info("Server stopped");
27155
+ logger$b.info("Server stopped");
27121
27156
  }
27122
27157
  resolve();
27123
27158
  });
27124
27159
  });
27125
27160
  }
27161
+ const logger$a = createLogger("Feedback");
27126
27162
  const SUPPORT_API = process.env.VESSEL_SUPPORT_API || process.env.VESSEL_PREMIUM_API || "https://vesselpremium.quantaintellect.com";
27127
27163
  const MAX_FEEDBACK_MESSAGE_LENGTH = 5e3;
27128
27164
  const FEEDBACK_REQUEST_TIMEOUT_MS = 15e3;
@@ -27158,7 +27194,11 @@ async function submitFeedback(payload) {
27158
27194
  source: payload.source
27159
27195
  })
27160
27196
  });
27161
- const data = await res.json().catch(() => ({}));
27197
+ const data = await readJsonResponse(
27198
+ res,
27199
+ {},
27200
+ (msg) => logger$a.warn("Failed to parse feedback response:", msg)
27201
+ );
27162
27202
  if (!res.ok) {
27163
27203
  return errorResult(data.error || `HTTP ${res.status}`);
27164
27204
  }
@@ -29480,12 +29520,14 @@ function renderReportAsMarkdown(report, traces) {
29480
29520
  }
29481
29521
  const logger$4 = createLogger("ResearchIPC");
29482
29522
  function registerResearchHandlers(getOrchestrator) {
29483
- electron.ipcMain.handle(Channels.RESEARCH_STATE_GET, () => {
29523
+ electron.ipcMain.handle(Channels.RESEARCH_STATE_GET, (event) => {
29524
+ assertTrustedIpcSender(event);
29484
29525
  return getOrchestrator().getState();
29485
29526
  });
29486
29527
  electron.ipcMain.handle(
29487
29528
  Channels.RESEARCH_START_BRIEF,
29488
- async (_event, query) => {
29529
+ async (event, query) => {
29530
+ assertTrustedIpcSender(event);
29489
29531
  try {
29490
29532
  const trimmedQuery = query.trim();
29491
29533
  if (!trimmedQuery) {
@@ -29502,7 +29544,8 @@ function registerResearchHandlers(getOrchestrator) {
29502
29544
  }
29503
29545
  }
29504
29546
  );
29505
- electron.ipcMain.handle(Channels.RESEARCH_CONFIRM_BRIEF, () => {
29547
+ electron.ipcMain.handle(Channels.RESEARCH_CONFIRM_BRIEF, (event) => {
29548
+ assertTrustedIpcSender(event);
29506
29549
  try {
29507
29550
  if (isToolGated("research_confirm_brief")) {
29508
29551
  return { accepted: false, reason: "premium" };
@@ -29520,7 +29563,8 @@ function registerResearchHandlers(getOrchestrator) {
29520
29563
  });
29521
29564
  electron.ipcMain.handle(
29522
29565
  Channels.RESEARCH_APPROVE_OBJECTIVES,
29523
- (_event, options) => {
29566
+ (event, options) => {
29567
+ assertTrustedIpcSender(event);
29524
29568
  try {
29525
29569
  if (isToolGated("research_approve_objectives")) {
29526
29570
  return { accepted: false, reason: "premium" };
@@ -29546,23 +29590,28 @@ function registerResearchHandlers(getOrchestrator) {
29546
29590
  );
29547
29591
  electron.ipcMain.handle(
29548
29592
  Channels.RESEARCH_SET_MODE,
29549
- (_event, mode) => {
29593
+ (event, mode) => {
29594
+ assertTrustedIpcSender(event);
29550
29595
  getOrchestrator().setSupervisionMode(mode);
29551
29596
  }
29552
29597
  );
29553
29598
  electron.ipcMain.handle(
29554
29599
  Channels.RESEARCH_SET_TRACES,
29555
- (_event, include) => {
29600
+ (event, include) => {
29601
+ assertTrustedIpcSender(event);
29556
29602
  getOrchestrator().setIncludeTraces(include);
29557
29603
  }
29558
29604
  );
29559
- electron.ipcMain.handle(Channels.RESEARCH_CANCEL, () => {
29605
+ electron.ipcMain.handle(Channels.RESEARCH_CANCEL, (event) => {
29606
+ assertTrustedIpcSender(event);
29560
29607
  getOrchestrator().cancel();
29561
29608
  });
29562
- electron.ipcMain.handle(Channels.RESEARCH_STOP_AND_SYNTHESIZE, () => {
29609
+ electron.ipcMain.handle(Channels.RESEARCH_STOP_AND_SYNTHESIZE, (event) => {
29610
+ assertTrustedIpcSender(event);
29563
29611
  getOrchestrator().stopAndSynthesizeCurrentFindings();
29564
29612
  });
29565
- electron.ipcMain.handle(Channels.RESEARCH_EXPORT_REPORT, async () => {
29613
+ electron.ipcMain.handle(Channels.RESEARCH_EXPORT_REPORT, async (event) => {
29614
+ assertTrustedIpcSender(event);
29566
29615
  try {
29567
29616
  if (isToolGated("research_export_report")) {
29568
29617
  return { accepted: false, reason: "premium" };