@quanta-intellect/vessel-browser 0.1.12 → 0.1.14

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.
@@ -1587,6 +1587,157 @@ function useBookmarks() {
1587
1587
  renameFolder: (id, newName, summary) => window.vessel.bookmarks.renameFolder(id, newName, summary)
1588
1588
  };
1589
1589
  }
1590
+ const MEMORY_STORAGE_KEY = "vessel.bookmark-context.memories";
1591
+ const MAX_MEMORY_LINES = 4;
1592
+ const MAX_MEMORY_CHARS = 420;
1593
+ function collapseWhitespace(value) {
1594
+ return value.replace(/\s+/g, " ").trim();
1595
+ }
1596
+ function cleanSnippet(value, maxLength = 140) {
1597
+ const cleaned = collapseWhitespace(
1598
+ value.replace(/`+/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1")
1599
+ );
1600
+ if (cleaned.length <= maxLength) return cleaned;
1601
+ return `${cleaned.slice(0, maxLength - 1).trimEnd()}...`;
1602
+ }
1603
+ function dedupe(values) {
1604
+ const seen = /* @__PURE__ */ new Set();
1605
+ const result = [];
1606
+ for (const value of values) {
1607
+ const normalized = value.trim().toLowerCase();
1608
+ if (!normalized || seen.has(normalized)) continue;
1609
+ seen.add(normalized);
1610
+ result.push(value.trim());
1611
+ }
1612
+ return result;
1613
+ }
1614
+ function bookmarkMemoryKey(url) {
1615
+ try {
1616
+ return new URL(url).hostname.replace(/^www\./i, "").toLowerCase();
1617
+ } catch {
1618
+ return url.trim().toLowerCase();
1619
+ }
1620
+ }
1621
+ function tokenize(value) {
1622
+ return dedupe(
1623
+ value.toLowerCase().split(/[^a-z0-9]+/i).filter((token) => token.length >= 4).slice(0, 8)
1624
+ );
1625
+ }
1626
+ function collectBookmarkConversationCues(bookmark, messages2) {
1627
+ const host = bookmarkMemoryKey(bookmark.url);
1628
+ const hostTokens = dedupe(
1629
+ host.split(".").filter((token) => token.length >= 4)
1630
+ );
1631
+ const titleTokens = tokenize(bookmark.title);
1632
+ const noteTokens = tokenize(bookmark.note || "").slice(0, 4);
1633
+ const urlLower = bookmark.url.toLowerCase();
1634
+ const cues = [];
1635
+ for (let index = messages2.length - 1; index >= 0; index -= 1) {
1636
+ const message = messages2[index];
1637
+ const content = collapseWhitespace(message.content);
1638
+ if (!content) continue;
1639
+ const lowered = content.toLowerCase();
1640
+ const matchedTokens = [...titleTokens, ...noteTokens].filter(
1641
+ (token) => lowered.includes(token)
1642
+ );
1643
+ const matchesBookmark = lowered.includes(host) || hostTokens.some((token) => lowered.includes(token)) || lowered.includes(urlLower) || matchedTokens.length >= 2 || matchedTokens.length >= 1 && titleTokens.length <= 1;
1644
+ if (!matchesBookmark) continue;
1645
+ const prefix = message.role === "user" ? "You" : "Assistant";
1646
+ cues.push(`${prefix}: ${cleanSnippet(content)}`);
1647
+ if (cues.length >= MAX_MEMORY_LINES) break;
1648
+ }
1649
+ return dedupe(cues);
1650
+ }
1651
+ function mergeBookmarkMemorySummary(existingSummary, cues) {
1652
+ const merged = dedupe([
1653
+ ...existingSummary ? existingSummary.split(" • ").map((item) => cleanSnippet(item, 160)) : [],
1654
+ ...cues
1655
+ ]).slice(0, MAX_MEMORY_LINES);
1656
+ if (merged.length === 0) return void 0;
1657
+ let summary = merged.join(" • ");
1658
+ if (summary.length > MAX_MEMORY_CHARS) {
1659
+ summary = `${summary.slice(0, MAX_MEMORY_CHARS - 3).trimEnd()}...`;
1660
+ }
1661
+ return summary;
1662
+ }
1663
+ function getStorage(storage) {
1664
+ if (storage) return storage;
1665
+ if (typeof window !== "undefined" && window.localStorage) {
1666
+ return window.localStorage;
1667
+ }
1668
+ return null;
1669
+ }
1670
+ function readMemoryMap(storage) {
1671
+ const target = getStorage(storage);
1672
+ if (!target) return {};
1673
+ try {
1674
+ const raw = target.getItem(MEMORY_STORAGE_KEY);
1675
+ if (!raw) return {};
1676
+ const parsed = JSON.parse(raw);
1677
+ return parsed && typeof parsed === "object" ? parsed : {};
1678
+ } catch {
1679
+ return {};
1680
+ }
1681
+ }
1682
+ function writeMemoryMap(map, storage) {
1683
+ const target = getStorage(storage);
1684
+ if (!target) return;
1685
+ try {
1686
+ target.setItem(MEMORY_STORAGE_KEY, JSON.stringify(map));
1687
+ } catch {
1688
+ }
1689
+ }
1690
+ function rememberBookmarkContext(args) {
1691
+ const key = bookmarkMemoryKey(args.bookmark.url);
1692
+ const map = readMemoryMap(args.storage);
1693
+ const existing = map[key];
1694
+ const cues = collectBookmarkConversationCues(args.bookmark, args.messages);
1695
+ const summary = mergeBookmarkMemorySummary(existing?.summary, cues);
1696
+ if (!summary) {
1697
+ return existing ?? null;
1698
+ }
1699
+ const entry = {
1700
+ summary,
1701
+ title: args.bookmark.title || args.bookmark.url,
1702
+ url: args.bookmark.url,
1703
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1704
+ };
1705
+ map[key] = entry;
1706
+ writeMemoryMap(map, args.storage);
1707
+ return entry;
1708
+ }
1709
+ function buildBookmarkContextDraft(args) {
1710
+ const lines = [
1711
+ "Saved bookmark context for the next step:",
1712
+ `- Title: ${args.bookmark.title || args.bookmark.url}`,
1713
+ `- URL: ${args.bookmark.url}`
1714
+ ];
1715
+ if (args.folder?.name) {
1716
+ lines.push(`- Folder: ${args.folder.name}`);
1717
+ }
1718
+ if (args.folder?.summary) {
1719
+ lines.push(`- Folder summary: ${cleanSnippet(args.folder.summary, 180)}`);
1720
+ }
1721
+ if (args.bookmark.note) {
1722
+ lines.push(`- Saved note: ${cleanSnippet(args.bookmark.note, 180)}`);
1723
+ }
1724
+ if (args.rememberedSummary) {
1725
+ lines.push(`- Remembered site context: ${args.rememberedSummary}`);
1726
+ }
1727
+ return lines.join("\n");
1728
+ }
1729
+ function buildAndRememberBookmarkContext(args) {
1730
+ const remembered = rememberBookmarkContext({
1731
+ bookmark: args.bookmark,
1732
+ messages: args.messages,
1733
+ storage: args.storage
1734
+ });
1735
+ return buildBookmarkContextDraft({
1736
+ bookmark: args.bookmark,
1737
+ folder: args.folder,
1738
+ rememberedSummary: remembered?.summary ?? null
1739
+ });
1740
+ }
1590
1741
  const {
1591
1742
  entries,
1592
1743
  setPrototypeOf,
@@ -2654,15 +2805,15 @@ function isTableBlock(text2) {
2654
2805
  const lines = text2.split("\n").filter((l) => l.trim());
2655
2806
  if (lines.length < 2) return false;
2656
2807
  const hasPipes = lines.every((l) => l.trim().includes("|"));
2657
- const hasSeparator = lines.some((l) => /^\|?\s*[-:]+[-|\s:]*$/.test(l.trim()));
2808
+ const hasSeparator = lines.some(
2809
+ (l) => /^\|?\s*[-:]+[-|\s:]*$/.test(l.trim())
2810
+ );
2658
2811
  return hasPipes && hasSeparator;
2659
2812
  }
2660
2813
  function renderTable(block) {
2661
2814
  const lines = block.split("\n").map((l) => l.trim()).filter(Boolean);
2662
2815
  const parseRow = (line) => line.replace(/^\|/, "").replace(/\|$/, "").split("|").map((cell) => cell.trim());
2663
- const sepIndex = lines.findIndex(
2664
- (l) => /^\|?\s*[-:]+[-|\s:]*$/.test(l)
2665
- );
2816
+ const sepIndex = lines.findIndex((l) => /^\|?\s*[-:]+[-|\s:]*$/.test(l));
2666
2817
  const headerRows = sepIndex > 0 ? lines.slice(0, sepIndex) : [lines[0]];
2667
2818
  const bodyRows = lines.slice(sepIndex + 1);
2668
2819
  const sepCells = sepIndex >= 0 ? parseRow(lines[sepIndex]) : [];
@@ -2677,10 +2828,14 @@ function renderTable(block) {
2677
2828
  return align && align !== "left" ? ` style="text-align:${align}"` : "";
2678
2829
  };
2679
2830
  const thead = headerRows.map(
2680
- (row) => `<tr>${parseRow(row).map((cell, i) => `<th${alignAttr(i)}>${applyInlineMarkdown(cell)}</th>`).join("")}</tr>`
2831
+ (row) => `<tr>${parseRow(row).map(
2832
+ (cell, i) => `<th${alignAttr(i)}>${applyInlineMarkdown(cell)}</th>`
2833
+ ).join("")}</tr>`
2681
2834
  ).join("");
2682
2835
  const tbody = bodyRows.map(
2683
- (row) => `<tr>${parseRow(row).map((cell, i) => `<td${alignAttr(i)}>${applyInlineMarkdown(cell)}</td>`).join("")}</tr>`
2836
+ (row) => `<tr>${parseRow(row).map(
2837
+ (cell, i) => `<td${alignAttr(i)}>${applyInlineMarkdown(cell)}</td>`
2838
+ ).join("")}</tr>`
2684
2839
  ).join("");
2685
2840
  return `<table><thead>${thead}</thead><tbody>${tbody}</tbody></table>`;
2686
2841
  }
@@ -2726,9 +2881,11 @@ function renderBlock(block) {
2726
2881
  const tableBlock = tableEndIdx > 0 ? tableLines.slice(0, tableEndIdx).join("\n") : tableLines.join("\n");
2727
2882
  const afterTable = tableEndIdx > 0 ? tableLines.slice(tableEndIdx).join("\n").trim() : "";
2728
2883
  let result = "";
2729
- if (beforeTable) result += `<p>${applyInlineMarkdown(beforeTable).replace(/\n/g, "<br>")}</p>`;
2884
+ if (beforeTable)
2885
+ result += `<p>${applyInlineMarkdown(beforeTable).replace(/\n/g, "<br>")}</p>`;
2730
2886
  result += renderTable(tableBlock);
2731
- if (afterTable) result += `<p>${applyInlineMarkdown(afterTable).replace(/\n/g, "<br>")}</p>`;
2887
+ if (afterTable)
2888
+ result += `<p>${applyInlineMarkdown(afterTable).replace(/\n/g, "<br>")}</p>`;
2732
2889
  return result;
2733
2890
  }
2734
2891
  if (trimmed.split("\n").every((line) => /^[-*+]\s+/.test(line))) {
@@ -2765,6 +2922,7 @@ const TOOL_ICONS = {
2765
2922
  flow_status: "◈",
2766
2923
  flow_end: "■",
2767
2924
  dismiss_popup: "✕",
2925
+ clear_overlays: "✕",
2768
2926
  wait_for: "◴",
2769
2927
  create_tab: "+",
2770
2928
  switch_tab: "⇥",
@@ -3104,6 +3262,28 @@ const Sidebar = (props) => {
3104
3262
  });
3105
3263
  onCleanup(unsubscribe);
3106
3264
  });
3265
+ createEffect(() => {
3266
+ const unsubscribe = window.vessel.bookmarks.onAddContextToChat((bookmarkId) => {
3267
+ const bookmark = bookmarksState2().bookmarks.find((item) => item.id === bookmarkId);
3268
+ if (!bookmark) return;
3269
+ const folder = bookmark.folderId === UNSORTED_FOLDER.id ? UNSORTED_FOLDER : bookmarksState2().folders.find((item) => item.id === bookmark.folderId) ?? null;
3270
+ const contextBlock = buildAndRememberBookmarkContext({
3271
+ bookmark,
3272
+ folder,
3273
+ messages: messages2()
3274
+ });
3275
+ setSidebarTab("chat");
3276
+ setChatInput((current) => current.trim() ? `${current.trim()}
3277
+
3278
+ ${contextBlock}` : contextBlock);
3279
+ queueMicrotask(() => {
3280
+ chatInputRef?.focus();
3281
+ const length = chatInputRef?.value.length ?? 0;
3282
+ chatInputRef?.setSelectionRange(length, length);
3283
+ });
3284
+ });
3285
+ onCleanup(unsubscribe);
3286
+ });
3107
3287
  const handleChatSend = async () => {
3108
3288
  const prompt = chatInput().trim();
3109
3289
  if (!prompt || isStreaming2()) return;
@@ -3136,6 +3316,7 @@ const Sidebar = (props) => {
3136
3316
  const [elapsedSeconds, setElapsedSeconds] = createSignal(0);
3137
3317
  let messagesContainerRef;
3138
3318
  let messagesEndRef;
3319
+ let chatInputRef;
3139
3320
  let hasInitializedMessageScroll = false;
3140
3321
  const recentActions = createMemo(() => runtimeState2().actions.slice(-8).reverse());
3141
3322
  const recentCheckpoints = createMemo(() => runtimeState2().checkpoints.slice(-5).reverse());
@@ -3621,6 +3802,7 @@ const Sidebar = (props) => {
3621
3802
  }), _el$138);
3622
3803
  insert(_el$139, () => formatBookmarkDate(bookmark.savedAt));
3623
3804
  _el$140.$$click = () => void removeBookmark(bookmark.id);
3805
+ createRenderEffect(() => setAttribute(_el$133, "data-bookmark-id", bookmark.id));
3624
3806
  return _el$133;
3625
3807
  })()
3626
3808
  }));
@@ -3868,6 +4050,8 @@ const Sidebar = (props) => {
3868
4050
  }
3869
4051
  };
3870
4052
  _el$91.$$input = (e) => setChatInput(e.currentTarget.value);
4053
+ var _ref$3 = chatInputRef;
4054
+ typeof _ref$3 === "function" ? use(_ref$3, _el$91) : chatInputRef = _el$91;
3871
4055
  _el$92.$$click = () => void handleChatSend();
3872
4056
  createRenderEffect(() => _el$92.disabled = !chatInput().trim() || isStreaming2());
3873
4057
  createRenderEffect(() => _el$91.value = chatInput());
@@ -4352,7 +4536,7 @@ const DevToolsPanel = () => {
4352
4536
  })();
4353
4537
  };
4354
4538
  delegateEvents(["click", "input"]);
4355
- var _tmpl$$1 = /* @__PURE__ */ template(`<div class=settings-field><label class=settings-label for=chat-provider>Provider</label><select id=chat-provider class="settings-input settings-select">`), _tmpl$2$1 = /* @__PURE__ */ template(`<div class=settings-field><label class=settings-label for=chat-api-key>API Key</label><input id=chat-api-key class=settings-input type=password>`), _tmpl$3 = /* @__PURE__ */ template(`<select id=chat-model class="settings-input settings-select"style=flex:1>`), _tmpl$4 = /* @__PURE__ */ template(`<p class=settings-hint style=color:var(--error)>Could not fetch models — check your API key and connection.`), _tmpl$5 = /* @__PURE__ */ template(`<div class=settings-field><label class=settings-label for=chat-model>Model</label><div style=display:flex;gap:6px;align-items:center><button type=button class=settings-refresh-btn title="Refresh model list">↺`), _tmpl$6 = /* @__PURE__ */ template(`<div class=settings-field><label class=settings-label for=chat-base-url>Base URL</label><input id=chat-base-url class=settings-input>`), _tmpl$7 = /* @__PURE__ */ template(`<div class=command-bar-overlay><div class=settings-panel><h2 class=settings-title>Runtime Settings</h2><div class=settings-callout><div class=settings-callout-title>External Agent Control</div><p class=settings-callout-copy>Vessel is configured to run under an external harness such as Hermes Agent or OpenClaw. Provider and model selection are not configured inside Vessel.</p></div><div class=settings-field><label class=settings-label for=mcp-port>MCP Port</label><input id=mcp-port class=settings-input placeholder=3100><p class=settings-hint>External harnesses connect to Vessel at <code>http://127.0.0.1:&lt;port&gt;/mcp</code>. Changing this value restarts the MCP server immediately.</p></div><div class=settings-field><label class=settings-label for=max-tool-iterations>Max Tool Iterations</label><input id=max-tool-iterations class=settings-input type=number min=10 max=1000 placeholder=200><p class=settings-hint>Maximum number of tool calls the AI agent can make per conversation turn before pausing. Higher values let the agent complete longer multi-step workflows without stopping. Range: 10–1000.</p></div><div class=settings-field><label class=settings-label for=obsidian-vault-path>Obsidian Vault Path</label><input id=obsidian-vault-path class=settings-input placeholder=/home/you/Documents/MyVault><p class=settings-hint>Optional. When set, Vessel memory tools can write markdown notes into this vault for research breadcrumbs and summaries.</p></div><div class=settings-field><label class=settings-label for=agent-transcript-mode>Agent Transcript Monitor</label><select id=agent-transcript-mode class="settings-input settings-select"><option value=off>Off</option><option value=summary>Summary HUD</option><option value=full>Full transcript</option></select><p class=settings-hint>Controls the in-browser transcript monitor when an external harness publishes reasoning or status updates into Vessel via the<code>vessel_publish_transcript</code> MCP tool. Summary HUD shows a compact 2-line status surface; Full transcript shows the recent entry list.</p></div><div class=settings-field><label class=settings-toggle><button type=button class=toggle-switch role=switch><span class=toggle-switch-thumb></span></button><span>Restore last browser session on launch</span></label></div><div class=settings-field><label class=settings-toggle><button type=button class=toggle-switch role=switch><span class=toggle-switch-thumb></span></button><span>Start bookmarks fresh on launch</span></label><p class=settings-hint>Off by default. When enabled, bookmark folders and saved pages are cleared each time Vessel starts.</p></div><div class=settings-section-divider></div><div class=settings-field><label class=settings-toggle><button type=button class=toggle-switch role=switch><span class=toggle-switch-thumb></span></button><span>Enable Chat Assistant</span></label><p class=settings-hint>Adds a Chat tab to the sidebar for conversing with an AI provider of your choice.</p></div><div class=settings-actions><button class=settings-save>Save</button><button class=settings-close>Close`), _tmpl$8 = /* @__PURE__ */ template(`<style>
4539
+ var _tmpl$$1 = /* @__PURE__ */ template(`<div class=settings-field><label class=settings-label for=chat-provider>Provider</label><select id=chat-provider class="settings-input settings-select">`), _tmpl$2$1 = /* @__PURE__ */ template(`<div class=settings-field><label class=settings-label for=chat-api-key>API Key</label><input id=chat-api-key class=settings-input type=password>`), _tmpl$3 = /* @__PURE__ */ template(`<select id=chat-model class="settings-input settings-select"style=flex:1>`), _tmpl$4 = /* @__PURE__ */ template(`<p class=settings-hint style=color:var(--error)>Could not fetch models — check your API key and connection.`), _tmpl$5 = /* @__PURE__ */ template(`<div class=settings-field><label class=settings-label for=chat-model>Model</label><div style=display:flex;gap:6px;align-items:center><button type=button class=settings-refresh-btn title="Refresh model list">↺`), _tmpl$6 = /* @__PURE__ */ template(`<div class=settings-field><label class=settings-label for=chat-base-url>Base URL</label><input id=chat-base-url class=settings-input>`), _tmpl$7 = /* @__PURE__ */ template(`<div class=command-bar-overlay><div class=settings-panel><h2 class=settings-title>Runtime Settings</h2><div class=settings-callout><div class=settings-callout-title>External Agent Control</div><p class=settings-callout-copy>Vessel is configured to run under an external harness such as Hermes Agent or OpenClaw. Provider and model selection are not configured inside Vessel.</p></div><div class=settings-field><label class=settings-label for=default-homepage>Homepage</label><input id=default-homepage class=settings-input placeholder=https://start.duckduckgo.com><p class=settings-hint>The page that opens when you create a new tab or launch Vessel without restoring a previous session.</p></div><div class=settings-field><label class=settings-label for=mcp-port>MCP Port</label><input id=mcp-port class=settings-input placeholder=3100><p class=settings-hint>External harnesses connect to Vessel at <code>http://127.0.0.1:&lt;port&gt;/mcp</code>. Changing this value restarts the MCP server immediately.</p></div><div class=settings-field><label class=settings-label for=max-tool-iterations>Max Tool Iterations</label><input id=max-tool-iterations class=settings-input type=number min=10 max=1000 placeholder=200><p class=settings-hint>Maximum number of tool calls the AI agent can make per conversation turn before pausing. Higher values let the agent complete longer multi-step workflows without stopping. Range: 10–1000.</p></div><div class=settings-field><label class=settings-label for=obsidian-vault-path>Obsidian Vault Path</label><input id=obsidian-vault-path class=settings-input placeholder=/home/you/Documents/MyVault><p class=settings-hint>Optional. When set, Vessel memory tools can write markdown notes into this vault for research breadcrumbs and summaries.</p></div><div class=settings-field><label class=settings-label for=agent-transcript-mode>Agent Transcript Monitor</label><select id=agent-transcript-mode class="settings-input settings-select"><option value=off>Off</option><option value=summary>Summary HUD</option><option value=full>Full transcript</option></select><p class=settings-hint>Controls the in-browser transcript monitor when an external harness publishes reasoning or status updates into Vessel via the<code>vessel_publish_transcript</code> MCP tool. Summary HUD shows a compact 2-line status surface; Full transcript shows the recent entry list.</p></div><div class=settings-field><label class=settings-toggle><button type=button class=toggle-switch role=switch><span class=toggle-switch-thumb></span></button><span>Restore last browser session on launch</span></label></div><div class=settings-field><label class=settings-toggle><button type=button class=toggle-switch role=switch><span class=toggle-switch-thumb></span></button><span>Start bookmarks fresh on launch</span></label><p class=settings-hint>Off by default. When enabled, bookmark folders and saved pages are cleared each time Vessel starts.</p></div><div class=settings-section-divider></div><div class=settings-field><label class=settings-toggle><button type=button class=toggle-switch role=switch><span class=toggle-switch-thumb></span></button><span>Enable Chat Assistant</span></label><p class=settings-hint>Adds a Chat tab to the sidebar for conversing with an AI provider of your choice.</p></div><div class=settings-actions><button class=settings-save>Save</button><button class=settings-close>Close`), _tmpl$8 = /* @__PURE__ */ template(`<style>
4356
4540
  .settings-panel {
4357
4541
  width: min(440px, calc(100vw - 32px));
4358
4542
  max-height: calc(100vh - 48px);
@@ -4656,6 +4840,7 @@ const Settings = () => {
4656
4840
  const [maxToolIterations, setMaxToolIterations] = createSignal("200");
4657
4841
  const [agentTranscriptMode, setAgentTranscriptMode] = createSignal("summary");
4658
4842
  const [health, setHealth] = createSignal(null);
4843
+ const [defaultUrl, setDefaultUrl] = createSignal("https://start.duckduckgo.com");
4659
4844
  const [status, setStatus] = createSignal(null);
4660
4845
  const [chatEnabled, setChatEnabled] = createSignal(false);
4661
4846
  const [chatProviderId, setChatProviderId] = createSignal("anthropic");
@@ -4713,6 +4898,7 @@ const Settings = () => {
4713
4898
  const loadState = async () => {
4714
4899
  const settings = await window.vessel.settings.get();
4715
4900
  const runtimeHealth = await window.vessel.settings.getHealth();
4901
+ setDefaultUrl(settings.defaultUrl ?? "https://start.duckduckgo.com");
4716
4902
  setAutoRestoreSession(settings.autoRestoreSession ?? true);
4717
4903
  setClearBookmarksOnLaunch(settings.clearBookmarksOnLaunch ?? false);
4718
4904
  setObsidianVaultPath(settings.obsidianVaultPath ?? "");
@@ -4747,6 +4933,7 @@ const Settings = () => {
4747
4933
  });
4748
4934
  return;
4749
4935
  }
4936
+ await window.vessel.settings.set("defaultUrl", defaultUrl().trim() || "https://start.duckduckgo.com");
4750
4937
  await window.vessel.settings.set("autoRestoreSession", autoRestoreSession());
4751
4938
  await window.vessel.settings.set("clearBookmarksOnLaunch", clearBookmarksOnLaunch());
4752
4939
  await window.vessel.settings.set("obsidianVaultPath", obsidianVaultPath());
@@ -4782,83 +4969,85 @@ const Settings = () => {
4782
4969
  },
4783
4970
  get children() {
4784
4971
  return [(() => {
4785
- var _el$ = _tmpl$7(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild, _el$4 = _el$3.nextSibling, _el$5 = _el$4.nextSibling, _el$6 = _el$5.firstChild, _el$7 = _el$6.nextSibling, _el$8 = _el$5.nextSibling, _el$9 = _el$8.firstChild, _el$0 = _el$9.nextSibling, _el$1 = _el$8.nextSibling, _el$10 = _el$1.firstChild, _el$11 = _el$10.nextSibling, _el$12 = _el$1.nextSibling, _el$13 = _el$12.firstChild, _el$14 = _el$13.nextSibling, _el$15 = _el$12.nextSibling, _el$16 = _el$15.firstChild, _el$17 = _el$16.firstChild, _el$18 = _el$15.nextSibling, _el$19 = _el$18.firstChild, _el$20 = _el$19.firstChild, _el$21 = _el$18.nextSibling, _el$22 = _el$21.nextSibling, _el$23 = _el$22.firstChild, _el$24 = _el$23.firstChild, _el$40 = _el$22.nextSibling, _el$41 = _el$40.firstChild, _el$42 = _el$41.nextSibling;
4972
+ var _el$ = _tmpl$7(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild, _el$4 = _el$3.nextSibling, _el$5 = _el$4.nextSibling, _el$6 = _el$5.firstChild, _el$7 = _el$6.nextSibling, _el$8 = _el$5.nextSibling, _el$9 = _el$8.firstChild, _el$0 = _el$9.nextSibling, _el$1 = _el$8.nextSibling, _el$10 = _el$1.firstChild, _el$11 = _el$10.nextSibling, _el$12 = _el$1.nextSibling, _el$13 = _el$12.firstChild, _el$14 = _el$13.nextSibling, _el$15 = _el$12.nextSibling, _el$16 = _el$15.firstChild, _el$17 = _el$16.nextSibling, _el$18 = _el$15.nextSibling, _el$19 = _el$18.firstChild, _el$20 = _el$19.firstChild, _el$21 = _el$18.nextSibling, _el$22 = _el$21.firstChild, _el$23 = _el$22.firstChild, _el$24 = _el$21.nextSibling, _el$25 = _el$24.nextSibling, _el$26 = _el$25.firstChild, _el$27 = _el$26.firstChild, _el$43 = _el$25.nextSibling, _el$44 = _el$43.firstChild, _el$45 = _el$44.nextSibling;
4786
4973
  addEventListener(_el$, "click", closeSettings);
4787
4974
  _el$2.$$keydown = handleKeyDown;
4788
4975
  _el$2.$$click = (e) => e.stopPropagation();
4789
- _el$7.$$input = (e) => setMcpPort(e.currentTarget.value);
4976
+ _el$7.$$input = (e) => setDefaultUrl(e.currentTarget.value);
4790
4977
  setAttribute(_el$7, "spellcheck", false);
4791
- _el$0.$$input = (e) => setMaxToolIterations(e.currentTarget.value);
4978
+ _el$0.$$input = (e) => setMcpPort(e.currentTarget.value);
4979
+ setAttribute(_el$0, "spellcheck", false);
4980
+ _el$11.$$input = (e) => setMaxToolIterations(e.currentTarget.value);
4792
4981
  insert(_el$2, createComponent(Show, {
4793
4982
  get when() {
4794
4983
  return health();
4795
4984
  },
4796
4985
  children: (currentHealth) => (() => {
4797
- var _el$44 = _tmpl$0(), _el$45 = _el$44.firstChild, _el$46 = _el$45.nextSibling, _el$47 = _el$46.firstChild, _el$49 = _el$47.nextSibling;
4798
- _el$49.nextSibling;
4799
- insert(_el$49, () => currentHealth().mcp.status);
4800
- insert(_el$46, () => currentHealth().mcp.message, null);
4801
- insert(_el$44, createComponent(Show, {
4986
+ var _el$47 = _tmpl$0(), _el$48 = _el$47.firstChild, _el$49 = _el$48.nextSibling, _el$50 = _el$49.firstChild, _el$52 = _el$50.nextSibling;
4987
+ _el$52.nextSibling;
4988
+ insert(_el$52, () => currentHealth().mcp.status);
4989
+ insert(_el$49, () => currentHealth().mcp.message, null);
4990
+ insert(_el$47, createComponent(Show, {
4802
4991
  get when() {
4803
4992
  return currentHealth().mcp.endpoint;
4804
4993
  },
4805
4994
  children: (endpoint) => (() => {
4806
- var _el$52 = _tmpl$1(), _el$53 = _el$52.firstChild, _el$54 = _el$53.nextSibling;
4807
- insert(_el$54, endpoint);
4808
- return _el$52;
4995
+ var _el$55 = _tmpl$1(), _el$56 = _el$55.firstChild, _el$57 = _el$56.nextSibling;
4996
+ insert(_el$57, endpoint);
4997
+ return _el$55;
4809
4998
  })()
4810
4999
  }), null);
4811
- insert(_el$44, createComponent(Show, {
5000
+ insert(_el$47, createComponent(Show, {
4812
5001
  get when() {
4813
5002
  return currentHealth().startupIssues.length > 0;
4814
5003
  },
4815
5004
  get children() {
4816
- var _el$51 = _tmpl$9();
4817
- insert(_el$51, () => currentHealth().startupIssues.map((issue) => (() => {
4818
- var _el$55 = _tmpl$10(), _el$56 = _el$55.firstChild, _el$57 = _el$56.nextSibling;
4819
- insert(_el$56, () => issue.title);
4820
- insert(_el$57, () => issue.detail);
4821
- insert(_el$55, createComponent(Show, {
5005
+ var _el$54 = _tmpl$9();
5006
+ insert(_el$54, () => currentHealth().startupIssues.map((issue) => (() => {
5007
+ var _el$58 = _tmpl$10(), _el$59 = _el$58.firstChild, _el$60 = _el$59.nextSibling;
5008
+ insert(_el$59, () => issue.title);
5009
+ insert(_el$60, () => issue.detail);
5010
+ insert(_el$58, createComponent(Show, {
4822
5011
  get when() {
4823
5012
  return issue.action;
4824
5013
  },
4825
5014
  children: (action) => (() => {
4826
- var _el$58 = _tmpl$11();
4827
- insert(_el$58, action);
4828
- return _el$58;
5015
+ var _el$61 = _tmpl$11();
5016
+ insert(_el$61, action);
5017
+ return _el$61;
4829
5018
  })()
4830
5019
  }), null);
4831
5020
  createRenderEffect((_p$) => {
4832
5021
  var _v$7 = !!(issue.severity === "warning"), _v$8 = !!(issue.severity === "error");
4833
- _v$7 !== _p$.e && _el$55.classList.toggle("warning", _p$.e = _v$7);
4834
- _v$8 !== _p$.t && _el$55.classList.toggle("error", _p$.t = _v$8);
5022
+ _v$7 !== _p$.e && _el$58.classList.toggle("warning", _p$.e = _v$7);
5023
+ _v$8 !== _p$.t && _el$58.classList.toggle("error", _p$.t = _v$8);
4835
5024
  return _p$;
4836
5025
  }, {
4837
5026
  e: void 0,
4838
5027
  t: void 0
4839
5028
  });
4840
- return _el$55;
5029
+ return _el$58;
4841
5030
  })()));
4842
- return _el$51;
5031
+ return _el$54;
4843
5032
  }
4844
5033
  }), null);
4845
- return _el$44;
5034
+ return _el$47;
4846
5035
  })()
4847
- }), _el$1);
4848
- _el$11.$$input = (e) => setObsidianVaultPath(e.currentTarget.value);
4849
- setAttribute(_el$11, "spellcheck", false);
4850
- _el$14.addEventListener("change", (e) => setAgentTranscriptMode(e.currentTarget.value));
4851
- _el$17.$$click = () => setAutoRestoreSession(!autoRestoreSession());
4852
- _el$20.$$click = () => setClearBookmarksOnLaunch(!clearBookmarksOnLaunch());
4853
- _el$24.$$click = () => setChatEnabled(!chatEnabled());
5036
+ }), _el$12);
5037
+ _el$14.$$input = (e) => setObsidianVaultPath(e.currentTarget.value);
5038
+ setAttribute(_el$14, "spellcheck", false);
5039
+ _el$17.addEventListener("change", (e) => setAgentTranscriptMode(e.currentTarget.value));
5040
+ _el$20.$$click = () => setAutoRestoreSession(!autoRestoreSession());
5041
+ _el$23.$$click = () => setClearBookmarksOnLaunch(!clearBookmarksOnLaunch());
5042
+ _el$27.$$click = () => setChatEnabled(!chatEnabled());
4854
5043
  insert(_el$2, createComponent(Show, {
4855
5044
  get when() {
4856
5045
  return chatEnabled();
4857
5046
  },
4858
5047
  get children() {
4859
5048
  return [(() => {
4860
- var _el$25 = _tmpl$$1(), _el$26 = _el$25.firstChild, _el$27 = _el$26.nextSibling;
4861
- _el$27.addEventListener("change", (e) => {
5049
+ var _el$28 = _tmpl$$1(), _el$29 = _el$28.firstChild, _el$30 = _el$29.nextSibling;
5050
+ _el$30.addEventListener("change", (e) => {
4862
5051
  const id = e.currentTarget.value;
4863
5052
  setChatProviderId(id);
4864
5053
  setChatModel("");
@@ -4867,65 +5056,65 @@ const Settings = () => {
4867
5056
  setProviderModels([]);
4868
5057
  setModelFetchState("idle");
4869
5058
  });
4870
- insert(_el$27, createComponent(For, {
5059
+ insert(_el$30, createComponent(For, {
4871
5060
  each: CHAT_PROVIDERS,
4872
5061
  children: (p) => (() => {
4873
- var _el$59 = _tmpl$12();
4874
- insert(_el$59, () => p.name);
4875
- createRenderEffect(() => _el$59.value = p.id);
4876
- return _el$59;
5062
+ var _el$62 = _tmpl$12();
5063
+ insert(_el$62, () => p.name);
5064
+ createRenderEffect(() => _el$62.value = p.id);
5065
+ return _el$62;
4877
5066
  })()
4878
5067
  }));
4879
- createRenderEffect(() => _el$27.value = chatProviderId());
4880
- return _el$25;
5068
+ createRenderEffect(() => _el$30.value = chatProviderId());
5069
+ return _el$28;
4881
5070
  })(), createComponent(Show, {
4882
5071
  get when() {
4883
5072
  return chatProviderMeta().requiresKey;
4884
5073
  },
4885
5074
  get children() {
4886
- var _el$28 = _tmpl$2$1(), _el$29 = _el$28.firstChild, _el$30 = _el$29.nextSibling;
4887
- _el$30.$$input = (e) => setChatApiKey(e.currentTarget.value);
4888
- setAttribute(_el$30, "spellcheck", false);
4889
- createRenderEffect(() => setAttribute(_el$30, "placeholder", chatProviderMeta().keyPlaceholder));
4890
- createRenderEffect(() => _el$30.value = chatApiKey());
4891
- return _el$28;
5075
+ var _el$31 = _tmpl$2$1(), _el$32 = _el$31.firstChild, _el$33 = _el$32.nextSibling;
5076
+ _el$33.$$input = (e) => setChatApiKey(e.currentTarget.value);
5077
+ setAttribute(_el$33, "spellcheck", false);
5078
+ createRenderEffect(() => setAttribute(_el$33, "placeholder", chatProviderMeta().keyPlaceholder));
5079
+ createRenderEffect(() => _el$33.value = chatApiKey());
5080
+ return _el$31;
4892
5081
  }
4893
5082
  }), (() => {
4894
- var _el$31 = _tmpl$5(), _el$32 = _el$31.firstChild, _el$33 = _el$32.nextSibling, _el$35 = _el$33.firstChild;
4895
- insert(_el$33, createComponent(Show, {
5083
+ var _el$34 = _tmpl$5(), _el$35 = _el$34.firstChild, _el$36 = _el$35.nextSibling, _el$38 = _el$36.firstChild;
5084
+ insert(_el$36, createComponent(Show, {
4896
5085
  get when() {
4897
5086
  return providerModels().length > 0;
4898
5087
  },
4899
5088
  get fallback() {
4900
5089
  return (() => {
4901
- var _el$60 = _tmpl$13();
4902
- _el$60.$$input = (e) => setChatModel(e.currentTarget.value);
4903
- setAttribute(_el$60, "spellcheck", false);
4904
- createRenderEffect(() => setAttribute(_el$60, "placeholder", modelFetchState() === "loading" ? "Fetching models…" : chatProviderMeta().requiresKey && !chatApiKey().trim() ? "Enter API key to load models" : chatProviderMeta().defaultModel || "model name"));
4905
- createRenderEffect(() => _el$60.value = chatModel());
4906
- return _el$60;
5090
+ var _el$63 = _tmpl$13();
5091
+ _el$63.$$input = (e) => setChatModel(e.currentTarget.value);
5092
+ setAttribute(_el$63, "spellcheck", false);
5093
+ createRenderEffect(() => setAttribute(_el$63, "placeholder", modelFetchState() === "loading" ? "Fetching models…" : chatProviderMeta().requiresKey && !chatApiKey().trim() ? "Enter API key to load models" : chatProviderMeta().defaultModel || "model name"));
5094
+ createRenderEffect(() => _el$63.value = chatModel());
5095
+ return _el$63;
4907
5096
  })();
4908
5097
  },
4909
5098
  get children() {
4910
- var _el$34 = _tmpl$3();
4911
- _el$34.addEventListener("change", (e) => setChatModel(e.currentTarget.value));
4912
- insert(_el$34, createComponent(For, {
5099
+ var _el$37 = _tmpl$3();
5100
+ _el$37.addEventListener("change", (e) => setChatModel(e.currentTarget.value));
5101
+ insert(_el$37, createComponent(For, {
4913
5102
  get each() {
4914
5103
  return providerModels();
4915
5104
  },
4916
5105
  children: (m) => (() => {
4917
- var _el$61 = _tmpl$12();
4918
- _el$61.value = m;
4919
- insert(_el$61, m);
4920
- return _el$61;
5106
+ var _el$64 = _tmpl$12();
5107
+ _el$64.value = m;
5108
+ insert(_el$64, m);
5109
+ return _el$64;
4921
5110
  })()
4922
5111
  }));
4923
- createRenderEffect(() => _el$34.value = chatModel());
4924
- return _el$34;
5112
+ createRenderEffect(() => _el$37.value = chatModel());
5113
+ return _el$37;
4925
5114
  }
4926
- }), _el$35);
4927
- _el$35.$$click = doFetchModels;
4928
- insert(_el$31, createComponent(Show, {
5115
+ }), _el$38);
5116
+ _el$38.$$click = doFetchModels;
5117
+ insert(_el$34, createComponent(Show, {
4929
5118
  get when() {
4930
5119
  return modelFetchState() === "error";
4931
5120
  },
@@ -4933,52 +5122,52 @@ const Settings = () => {
4933
5122
  return _tmpl$4();
4934
5123
  }
4935
5124
  }), null);
4936
- createRenderEffect(() => _el$35.disabled = modelFetchState() === "loading");
4937
- return _el$31;
5125
+ createRenderEffect(() => _el$38.disabled = modelFetchState() === "loading");
5126
+ return _el$34;
4938
5127
  })(), createComponent(Show, {
4939
5128
  get when() {
4940
5129
  return chatProviderMeta().needsBaseUrl || chatProviderId() === "custom";
4941
5130
  },
4942
5131
  get children() {
4943
- var _el$37 = _tmpl$6(), _el$38 = _el$37.firstChild, _el$39 = _el$38.nextSibling;
4944
- _el$39.$$input = (e) => setChatBaseUrl(e.currentTarget.value);
4945
- setAttribute(_el$39, "spellcheck", false);
4946
- createRenderEffect(() => setAttribute(_el$39, "placeholder", chatProviderMeta().defaultBaseUrl ?? "https://..."));
4947
- createRenderEffect(() => _el$39.value = chatBaseUrl());
4948
- return _el$37;
5132
+ var _el$40 = _tmpl$6(), _el$41 = _el$40.firstChild, _el$42 = _el$41.nextSibling;
5133
+ _el$42.$$input = (e) => setChatBaseUrl(e.currentTarget.value);
5134
+ setAttribute(_el$42, "spellcheck", false);
5135
+ createRenderEffect(() => setAttribute(_el$42, "placeholder", chatProviderMeta().defaultBaseUrl ?? "https://..."));
5136
+ createRenderEffect(() => _el$42.value = chatBaseUrl());
5137
+ return _el$40;
4949
5138
  }
4950
5139
  })];
4951
5140
  }
4952
- }), _el$40);
4953
- _el$41.$$click = handleSave;
4954
- addEventListener(_el$42, "click", closeSettings);
5141
+ }), _el$43);
5142
+ _el$44.$$click = handleSave;
5143
+ addEventListener(_el$45, "click", closeSettings);
4955
5144
  insert(_el$2, createComponent(Show, {
4956
5145
  get when() {
4957
5146
  return status();
4958
5147
  },
4959
5148
  children: (currentStatus) => (() => {
4960
- var _el$62 = _tmpl$14();
4961
- insert(_el$62, () => currentStatus().text);
5149
+ var _el$65 = _tmpl$14();
5150
+ insert(_el$65, () => currentStatus().text);
4962
5151
  createRenderEffect((_p$) => {
4963
5152
  var _v$9 = !!(currentStatus().kind === "success"), _v$0 = !!(currentStatus().kind === "error");
4964
- _v$9 !== _p$.e && _el$62.classList.toggle("success", _p$.e = _v$9);
4965
- _v$0 !== _p$.t && _el$62.classList.toggle("error", _p$.t = _v$0);
5153
+ _v$9 !== _p$.e && _el$65.classList.toggle("success", _p$.e = _v$9);
5154
+ _v$0 !== _p$.t && _el$65.classList.toggle("error", _p$.t = _v$0);
4966
5155
  return _p$;
4967
5156
  }, {
4968
5157
  e: void 0,
4969
5158
  t: void 0
4970
5159
  });
4971
- return _el$62;
5160
+ return _el$65;
4972
5161
  })()
4973
5162
  }), null);
4974
5163
  createRenderEffect((_p$) => {
4975
5164
  var _v$ = !!autoRestoreSession(), _v$2 = autoRestoreSession(), _v$3 = !!clearBookmarksOnLaunch(), _v$4 = clearBookmarksOnLaunch(), _v$5 = !!chatEnabled(), _v$6 = chatEnabled();
4976
- _v$ !== _p$.e && _el$17.classList.toggle("on", _p$.e = _v$);
4977
- _v$2 !== _p$.t && setAttribute(_el$17, "aria-checked", _p$.t = _v$2);
4978
- _v$3 !== _p$.a && _el$20.classList.toggle("on", _p$.a = _v$3);
4979
- _v$4 !== _p$.o && setAttribute(_el$20, "aria-checked", _p$.o = _v$4);
4980
- _v$5 !== _p$.i && _el$24.classList.toggle("on", _p$.i = _v$5);
4981
- _v$6 !== _p$.n && setAttribute(_el$24, "aria-checked", _p$.n = _v$6);
5165
+ _v$ !== _p$.e && _el$20.classList.toggle("on", _p$.e = _v$);
5166
+ _v$2 !== _p$.t && setAttribute(_el$20, "aria-checked", _p$.t = _v$2);
5167
+ _v$3 !== _p$.a && _el$23.classList.toggle("on", _p$.a = _v$3);
5168
+ _v$4 !== _p$.o && setAttribute(_el$23, "aria-checked", _p$.o = _v$4);
5169
+ _v$5 !== _p$.i && _el$27.classList.toggle("on", _p$.i = _v$5);
5170
+ _v$6 !== _p$.n && setAttribute(_el$27, "aria-checked", _p$.n = _v$6);
4982
5171
  return _p$;
4983
5172
  }, {
4984
5173
  e: void 0,
@@ -4988,10 +5177,11 @@ const Settings = () => {
4988
5177
  i: void 0,
4989
5178
  n: void 0
4990
5179
  });
4991
- createRenderEffect(() => _el$7.value = mcpPort());
4992
- createRenderEffect(() => _el$0.value = maxToolIterations());
4993
- createRenderEffect(() => _el$11.value = obsidianVaultPath());
4994
- createRenderEffect(() => _el$14.value = agentTranscriptMode());
5180
+ createRenderEffect(() => _el$7.value = defaultUrl());
5181
+ createRenderEffect(() => _el$0.value = mcpPort());
5182
+ createRenderEffect(() => _el$11.value = maxToolIterations());
5183
+ createRenderEffect(() => _el$14.value = obsidianVaultPath());
5184
+ createRenderEffect(() => _el$17.value = agentTranscriptMode());
4995
5185
  return _el$;
4996
5186
  })(), _tmpl$8()];
4997
5187
  }
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Vessel</title>
7
- <script type="module" crossorigin src="./assets/index-Do3B3G1W.js"></script>
7
+ <script type="module" crossorigin src="./assets/index-CvRVBELV.js"></script>
8
8
  <link rel="stylesheet" crossorigin href="./assets/index-DMd-y6tm.css">
9
9
  </head>
10
10
  <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.12",
4
+ "version": "0.1.14",
5
5
  "description": "AI-native web browser for Linux — persistent browser runtime for autonomous agents with human supervision",
6
6
  "main": "./out/main/index.js",
7
7
  "bin": {