@quanta-intellect/vessel-browser 0.1.80 → 0.1.81

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
@@ -23941,8 +23941,7 @@ const THIRD_PARTY_PATH_PATTERNS = [
23941
23941
  /\/beacon/i,
23942
23942
  /\/pixel/i
23943
23943
  ];
23944
- let installed = false;
23945
- const defaultSessionTabManagers = /* @__PURE__ */ new Set();
23944
+ const EMPTY_BLOCKED_FRAME_URL = "data:text/html;charset=utf-8,%3C!doctype%20html%3E%3Chtml%3E%3Cbody%3E%3C!--%20blocked%20by%20Vessel%20ad%20blocker%20--%3E%3C%2Fbody%3E%3C%2Fhtml%3E";
23946
23945
  function normalizeHostname(value) {
23947
23946
  return value.trim().toLowerCase().replace(/\.$/, "");
23948
23947
  }
@@ -23980,11 +23979,20 @@ function shouldBlockRequest(details) {
23980
23979
  if (BLOCKED_HOST_SUFFIXES.some((suffix) => hostnameMatches(hostname, suffix))) {
23981
23980
  return true;
23982
23981
  }
23983
- const firstPartyHost = parseHostname(details.referrer) || parseHostname(details.initiator || "");
23982
+ const firstPartyHost = parseHostname(details.referrer || "") || parseHostname(details.initiator || "");
23984
23983
  if (!isThirdParty(parsed, firstPartyHost)) return false;
23985
23984
  const candidate = `${hostname}${parsed.pathname}${parsed.search}`;
23986
23985
  return THIRD_PARTY_PATH_PATTERNS.some((pattern) => pattern.test(candidate));
23987
23986
  }
23987
+ function getAdBlockDecision(details) {
23988
+ if (!shouldBlockRequest(details)) return { cancel: false };
23989
+ if (details.resourceType === "subFrame") {
23990
+ return { redirectURL: EMPTY_BLOCKED_FRAME_URL };
23991
+ }
23992
+ return { cancel: true };
23993
+ }
23994
+ let installed = false;
23995
+ const defaultSessionTabManagers = /* @__PURE__ */ new Set();
23988
23996
  function installAdBlocking(tabManager) {
23989
23997
  defaultSessionTabManagers.add(tabManager);
23990
23998
  if (installed) return;
@@ -24002,7 +24010,7 @@ function installAdBlocking(tabManager) {
24002
24010
  callback({});
24003
24011
  return;
24004
24012
  }
24005
- callback({ cancel: shouldBlockRequest(details) });
24013
+ callback(getAdBlockDecision(details));
24006
24014
  });
24007
24015
  }
24008
24016
  function unregisterAdBlockingTabManager(tabManager) {
@@ -24019,7 +24027,7 @@ function installAdBlockingForSession(ses, tabManager) {
24019
24027
  callback({});
24020
24028
  return;
24021
24029
  }
24022
- callback({ cancel: shouldBlockRequest(details) });
24030
+ callback(getAdBlockDecision(details));
24023
24031
  });
24024
24032
  }
24025
24033
  const defaultDownloadViews = /* @__PURE__ */ new Set();
@@ -2881,15 +2881,16 @@ function cleanDiffSummaryText(value) {
2881
2881
  return value.replace(
2882
2882
  /```[\s\S]*?```/g,
2883
2883
  (match) => match.replace(/```[a-z]*\n?/gi, "").replace(/```/g, "")
2884
- ).replace(/!\[([^\]]*)\]\([^)]+\)/g, "$1").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/(\*\*|__)(.*?)\1/g, "$2").replace(/(\*|_)(.*?)\1/g, "$2").replace(/^#{1,6}\s+/gm, "").replace(/^\s*[-*+]\s+/gm, "").replace(/^\s*>\s?/gm, "").replace(/\s+/g, " ").trim();
2884
+ ).replace(/!\[([^\]]*)\]\([^)]+\)/g, "$1").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/(\*\*|__)(.*?)\1/g, "$2").replace(/(\*|_)(.*?)\1/g, "$2").replace(/^\s*>\s?/gm, "").replace(/^#{1,6}\s+/gm, "").replace(/^\s*[-*+]\s+/gm, "").replace(/\s+/g, " ").trim();
2885
2885
  }
2886
2886
  function formatDiffSectionLabel(section) {
2887
- const normalized = section.trim().toLowerCase();
2888
- return SECTION_LABELS[normalized] ?? section.trim();
2887
+ const trimmed = section.trim();
2888
+ const normalized = trimmed.toLowerCase();
2889
+ return SECTION_LABELS[normalized] ?? trimmed;
2889
2890
  }
2890
2891
  function parseDiffSummaryParts(summary) {
2891
- return summary.split(/\s+\|\s+/).map((part) => {
2892
- const match = part.match(/^([a-z]+):\s*(.+)$/i);
2892
+ const parts = summary.split(/\s*\|\s*/).map((part) => {
2893
+ const match = part.match(/^([a-z][a-z\s-]*):\s*(.+)$/i);
2893
2894
  if (!match) {
2894
2895
  return { text: cleanDiffSummaryText(part) };
2895
2896
  }
@@ -2898,6 +2899,48 @@ function parseDiffSummaryParts(summary) {
2898
2899
  text: cleanDiffSummaryText(match[2])
2899
2900
  };
2900
2901
  }).filter((part) => part.text.length > 0);
2902
+ return parts.length > 0 ? parts : [{ text: "Change detected." }];
2903
+ }
2904
+ function resolveNow(options) {
2905
+ if (options?.now instanceof Date) return options.now.getTime();
2906
+ return Date.now();
2907
+ }
2908
+ function formatRelativeTime(isoDate, options) {
2909
+ const timestamp = new Date(isoDate).getTime();
2910
+ if (Number.isNaN(timestamp)) return "recently";
2911
+ const now2 = resolveNow(options);
2912
+ if (Number.isNaN(now2)) return "recently";
2913
+ const diff = Math.max(0, now2 - timestamp);
2914
+ const mins = Math.floor(diff / 6e4);
2915
+ if (mins < 1) return "just now";
2916
+ if (mins < 60) return `${mins}m ago`;
2917
+ const hours = Math.floor(mins / 60);
2918
+ if (hours < 24) return `${hours}h ago`;
2919
+ const days = Math.floor(hours / 24);
2920
+ if (days < 7) return `${days}d ago`;
2921
+ return new Date(timestamp).toLocaleDateString();
2922
+ }
2923
+ function formatShortDateTime(isoDate) {
2924
+ const date = new Date(isoDate);
2925
+ if (Number.isNaN(date.getTime())) return "Unknown time";
2926
+ return date.toLocaleString([], {
2927
+ month: "short",
2928
+ day: "numeric",
2929
+ hour: "numeric",
2930
+ minute: "2-digit"
2931
+ });
2932
+ }
2933
+ function formatElapsedTime(startIso, endIso) {
2934
+ const start = new Date(startIso).getTime();
2935
+ const end = new Date(endIso).getTime();
2936
+ if (Number.isNaN(start) || Number.isNaN(end)) return "unknown duration";
2937
+ const elapsedMs = Math.max(0, end - start);
2938
+ const secs = Math.round(elapsedMs / 1e3);
2939
+ if (secs < 60) return `${secs}s`;
2940
+ const mins = Math.round(secs / 60);
2941
+ if (mins < 60) return `${mins}m`;
2942
+ const hours = Math.round(mins / 60);
2943
+ return `${hours}h`;
2901
2944
  }
2902
2945
  const SEARCH_ENGINE_PRESETS = {
2903
2946
  duckduckgo: { label: "DuckDuckGo", url: "https://duckduckgo.com/?q=" },
@@ -2942,8 +2985,14 @@ const AddressBar = (props) => {
2942
2985
  const [selectedIndex, setSelectedIndex] = createSignal(-1);
2943
2986
  const [searchEngine, setSearchEngine] = createSignal("duckduckgo");
2944
2987
  const [showSecurityPopup, setShowSecurityPopup] = createSignal(false);
2988
+ const [hasEditedAddress, setHasEditedAddress] = createSignal(false);
2945
2989
  const now2 = useNow();
2946
2990
  let inputRef;
2991
+ let addressBlurTimer = null;
2992
+ let skipNextAddressBlurSync = false;
2993
+ onCleanup(() => {
2994
+ if (addressBlurTimer) clearTimeout(addressBlurTimer);
2995
+ });
2947
2996
  const securityState = createMemo(() => {
2948
2997
  const tabId = activeTabId2();
2949
2998
  return tabId ? getSecurityState(tabId) : void 0;
@@ -2994,26 +3043,6 @@ const AddressBar = (props) => {
2994
3043
  }
2995
3044
  await window.vessel.ui.openSidebarTab("diff");
2996
3045
  };
2997
- const formatRelativeTime2 = (isoDate) => {
2998
- const diff = Date.now() - new Date(isoDate).getTime();
2999
- const mins = Math.floor(diff / 6e4);
3000
- if (mins < 1) return "just now";
3001
- if (mins < 60) return `${mins}m ago`;
3002
- const hours = Math.floor(mins / 60);
3003
- if (hours < 24) return `${hours}h ago`;
3004
- const days = Math.floor(hours / 24);
3005
- if (days < 7) return `${days}d ago`;
3006
- return new Date(isoDate).toLocaleDateString();
3007
- };
3008
- const formatElapsed = (startIso, endIso) => {
3009
- const elapsedMs = Math.max(0, new Date(endIso).getTime() - new Date(startIso).getTime());
3010
- const secs = Math.round(elapsedMs / 1e3);
3011
- if (secs < 60) return `${secs}s`;
3012
- const mins = Math.round(secs / 60);
3013
- if (mins < 60) return `${mins}m`;
3014
- const hours = Math.round(mins / 60);
3015
- return `${hours}h`;
3016
- };
3017
3046
  const getChangeKindLabel = (kind) => kind === "added" ? "Added" : kind === "removed" ? "Removed" : "Changed";
3018
3047
  createEffect(() => {
3019
3048
  if (isPrivateWindow) return;
@@ -3031,10 +3060,16 @@ const AddressBar = (props) => {
3031
3060
  }
3032
3061
  });
3033
3062
  });
3063
+ const syncInputValueFromActiveTab = () => {
3064
+ const tab = activeTab();
3065
+ if (!tab) return;
3066
+ setInputValue(tab.url === "about:blank" ? "" : tab.url);
3067
+ };
3034
3068
  createEffect(() => {
3035
3069
  const tab = activeTab();
3036
- if (tab && !inputRef?.matches(":focus")) {
3037
- setInputValue(tab.url === "about:blank" ? "" : tab.url);
3070
+ const inputHasFocus = inputRef && document.activeElement === inputRef;
3071
+ if (tab && !hasEditedAddress() && !inputHasFocus) {
3072
+ syncInputValueFromActiveTab();
3038
3073
  setShowSuggestions(false);
3039
3074
  setSelectedIndex(-1);
3040
3075
  }
@@ -3117,12 +3152,46 @@ const AddressBar = (props) => {
3117
3152
  cancelled = true;
3118
3153
  });
3119
3154
  });
3120
- const selectSuggestion = (url) => {
3121
- setInputValue(url);
3155
+ const clearAddressBlurTimer = () => {
3156
+ if (!addressBlurTimer) return;
3157
+ clearTimeout(addressBlurTimer);
3158
+ addressBlurTimer = null;
3159
+ };
3160
+ const closeAddressSuggestions = () => {
3122
3161
  setShowSuggestions(false);
3123
3162
  setSelectedIndex(-1);
3163
+ };
3164
+ const commitAddressNavigation = (url) => {
3165
+ clearAddressBlurTimer();
3166
+ setHasEditedAddress(false);
3167
+ skipNextAddressBlurSync = true;
3124
3168
  navigate(url);
3125
3169
  inputRef?.blur();
3170
+ closeAddressSuggestions();
3171
+ };
3172
+ const cancelAddressEditing = () => {
3173
+ clearAddressBlurTimer();
3174
+ setHasEditedAddress(false);
3175
+ syncInputValueFromActiveTab();
3176
+ inputRef?.blur();
3177
+ closeAddressSuggestions();
3178
+ };
3179
+ const scheduleAddressBlurReset = () => {
3180
+ clearAddressBlurTimer();
3181
+ addressBlurTimer = setTimeout(() => {
3182
+ setHasEditedAddress(false);
3183
+ if (skipNextAddressBlurSync) {
3184
+ skipNextAddressBlurSync = false;
3185
+ } else {
3186
+ syncInputValueFromActiveTab();
3187
+ }
3188
+ closeAddressSuggestions();
3189
+ addressBlurTimer = null;
3190
+ }, 150);
3191
+ };
3192
+ const selectSuggestion = (url) => {
3193
+ setInputValue(url);
3194
+ commitAddressNavigation(url);
3126
3195
  };
3127
3196
  const handleSubmit = (e) => {
3128
3197
  e.preventDefault();
@@ -3132,11 +3201,7 @@ const AddressBar = (props) => {
3132
3201
  selectSuggestion(items[idx].url);
3133
3202
  } else {
3134
3203
  const val = inputValue().trim();
3135
- if (val) {
3136
- navigate(val);
3137
- inputRef?.blur();
3138
- setShowSuggestions(false);
3139
- }
3204
+ if (val) commitAddressNavigation(val);
3140
3205
  }
3141
3206
  };
3142
3207
  const handleInputKeyDown = (e) => {
@@ -3156,10 +3221,11 @@ const AddressBar = (props) => {
3156
3221
  }
3157
3222
  } else if (e.key === "Escape") {
3158
3223
  if (showSuggestions()) {
3159
- setShowSuggestions(false);
3160
- setSelectedIndex(-1);
3224
+ syncInputValueFromActiveTab();
3225
+ setHasEditedAddress(false);
3226
+ closeAddressSuggestions();
3161
3227
  } else {
3162
- inputRef?.blur();
3228
+ cancelAddressEditing();
3163
3229
  }
3164
3230
  }
3165
3231
  };
@@ -3242,18 +3308,17 @@ const AddressBar = (props) => {
3242
3308
  }), _el$11);
3243
3309
  _el$12.addEventListener("submit", handleSubmit);
3244
3310
  _el$13.addEventListener("blur", () => {
3245
- setTimeout(() => {
3246
- setShowSuggestions(false);
3247
- setSelectedIndex(-1);
3248
- }, 150);
3311
+ scheduleAddressBlurReset();
3249
3312
  });
3250
3313
  _el$13.$$keydown = handleInputKeyDown;
3251
3314
  _el$13.addEventListener("focus", (e) => {
3315
+ clearAddressBlurTimer();
3252
3316
  e.currentTarget.select();
3253
3317
  const query = inputValue().trim();
3254
3318
  if (query.length >= 2) setShowSuggestions(true);
3255
3319
  });
3256
3320
  _el$13.$$input = (e) => {
3321
+ setHasEditedAddress(true);
3257
3322
  setInputValue(e.currentTarget.value);
3258
3323
  setShowSuggestions(true);
3259
3324
  setSelectedIndex(-1);
@@ -3336,7 +3401,7 @@ const AddressBar = (props) => {
3336
3401
  var _el$19 = _tmpl$0$5(), _el$20 = _el$19.firstChild, _el$21 = _el$20.firstChild, _el$22 = _el$21.firstChild, _el$23 = _el$22.nextSibling;
3337
3402
  _el$23.firstChild;
3338
3403
  var _el$30 = _el$21.nextSibling, _el$31 = _el$30.firstChild, _el$32 = _el$31.nextSibling;
3339
- insert(_el$23, () => formatRelativeTime2(pageDiff().oldSnapshot.capturedAt), null);
3404
+ insert(_el$23, () => formatRelativeTime(pageDiff().oldSnapshot.capturedAt), null);
3340
3405
  insert(_el$21, createComponent(Show, {
3341
3406
  get when() {
3342
3407
  return memo(() => !!((pageDiff().burstCount || 0) > 1 && pageDiff().firstDetectedAt))() && pageDiff().lastDetectedAt;
@@ -3345,7 +3410,7 @@ const AddressBar = (props) => {
3345
3410
  var _el$25 = _tmpl$8$8(), _el$26 = _el$25.firstChild, _el$29 = _el$26.nextSibling;
3346
3411
  _el$29.nextSibling;
3347
3412
  insert(_el$25, () => pageDiff().burstCount, _el$29);
3348
- insert(_el$25, () => formatElapsed(pageDiff().firstDetectedAt, pageDiff().lastDetectedAt), null);
3413
+ insert(_el$25, () => formatElapsedTime(pageDiff().firstDetectedAt, pageDiff().lastDetectedAt), null);
3349
3414
  return _el$25;
3350
3415
  }
3351
3416
  }), null);
@@ -3366,7 +3431,7 @@ const AddressBar = (props) => {
3366
3431
  var _el$55 = _tmpl$20$2(), _el$56 = _el$55.firstChild, _el$57 = _el$56.nextSibling;
3367
3432
  insert(_el$56, (() => {
3368
3433
  var _c$2 = memo(() => i() === 0);
3369
- return () => _c$2() ? "Latest" : formatRelativeTime2(burst.detectedAt);
3434
+ return () => _c$2() ? "Latest" : formatRelativeTime(burst.detectedAt);
3370
3435
  })());
3371
3436
  insert(_el$57, createComponent(For, {
3372
3437
  get each() {
@@ -7313,23 +7378,6 @@ const AutomationTab = (props) => {
7313
7378
  };
7314
7379
  delegateEvents(["click", "input", "keydown", "contextmenu"]);
7315
7380
  var _tmpl$$b = /* @__PURE__ */ template(`<div class=agent-muted>Loading...`), _tmpl$2$b = /* @__PURE__ */ template(`<div class=agent-muted>`), _tmpl$3$a = /* @__PURE__ */ template(`<div class=agent-muted>No changes detected yet.`), _tmpl$4$a = /* @__PURE__ */ template(`<div class=page-diff-timeline-header><div class=agent-section-title>Change history for this page</div><div class=agent-muted>Newest detections are first. Each entry is a saved change burst.`), _tmpl$5$7 = /* @__PURE__ */ template(`<div class=page-diff-history-list>`), _tmpl$6$7 = /* @__PURE__ */ template(`<div class=page-diff-timeline>`), _tmpl$7$7 = /* @__PURE__ */ template(`<div class=page-diff-history-item><div class=page-diff-history-time><span class=page-diff-history-label></span><span></span></div><div class=page-diff-history-card><div class=page-diff-history-summary-list></div><div class=page-diff-history-position>Entry <!> of `), _tmpl$8$6 = /* @__PURE__ */ template(`<span class=page-diff-history-summary-section>`), _tmpl$9$4 = /* @__PURE__ */ template(`<div class=page-diff-history-summary-row><span class=page-diff-history-summary>`);
7316
- const formatChangeTime = (isoDate) => new Date(isoDate).toLocaleString([], {
7317
- month: "short",
7318
- day: "numeric",
7319
- hour: "numeric",
7320
- minute: "2-digit"
7321
- });
7322
- const formatRelativeTime = (isoDate) => {
7323
- const diff = Date.now() - new Date(isoDate).getTime();
7324
- const mins = Math.floor(diff / 6e4);
7325
- if (mins < 1) return "just now";
7326
- if (mins < 60) return `${mins}m ago`;
7327
- const hours = Math.floor(mins / 60);
7328
- if (hours < 24) return `${hours}h ago`;
7329
- const days = Math.floor(hours / 24);
7330
- if (days < 7) return `${days}d ago`;
7331
- return new Date(isoDate).toLocaleDateString();
7332
- };
7333
7381
  const PageDiffTimeline = () => {
7334
7382
  const {
7335
7383
  activeTab
@@ -7426,7 +7474,7 @@ const PageDiffTimeline = () => {
7426
7474
  var _c$ = memo(() => i() === 0);
7427
7475
  return () => _c$() ? "Latest change" : formatRelativeTime(burst.detectedAt);
7428
7476
  })());
7429
- insert(_el$0, () => formatChangeTime(burst.detectedAt));
7477
+ insert(_el$0, () => formatShortDateTime(burst.detectedAt));
7430
7478
  insert(_el$10, createComponent(For, {
7431
7479
  get each() {
7432
7480
  return parseDiffSummaryParts(burst.summary);
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'; font-src 'self' data:;" />
7
7
  <title>Vessel</title>
8
- <script type="module" crossorigin src="./assets/index-Dhg4KPX1.js"></script>
8
+ <script type="module" crossorigin src="./assets/index-DOJa9vgV.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="./assets/index-CHSGQlQr.css">
10
10
  </head>
11
11
  <body>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@quanta-intellect/vessel-browser",
3
3
  "mcpName": "io.github.unmodeled-tyler/vessel-browser",
4
- "version": "0.1.80",
4
+ "version": "0.1.81",
5
5
  "description": "AI-native web browser runtime for autonomous agents with human supervision",
6
6
  "main": "./out/main/index.js",
7
7
  "bin": {