@quanta-intellect/vessel-browser 0.1.15 → 0.1.16

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
@@ -4406,6 +4406,19 @@ function setMcpHealth(update) {
4406
4406
  }
4407
4407
  }
4408
4408
  }
4409
+ function isRichToolResult(value) {
4410
+ return typeof value === "object" && value !== null && value.__richResult === true;
4411
+ }
4412
+ function makeImageResult(base64, description, mediaType = "image/png") {
4413
+ const result = {
4414
+ __richResult: true,
4415
+ content: [
4416
+ { type: "text", text: description },
4417
+ { type: "image", mediaType, base64 }
4418
+ ]
4419
+ };
4420
+ return JSON.stringify(result);
4421
+ }
4409
4422
  const DEFAULT_MAX_ITERATIONS$1 = 200;
4410
4423
  class AnthropicProvider {
4411
4424
  client;
@@ -4437,7 +4450,7 @@ class AnthropicProvider {
4437
4450
  }
4438
4451
  }
4439
4452
  } catch (err) {
4440
- if (err.name !== "AbortError") {
4453
+ if (err instanceof Error && err.name !== "AbortError") {
4441
4454
  onChunk(`
4442
4455
 
4443
4456
  [Error: ${err.message}]`);
@@ -4460,7 +4473,6 @@ class AnthropicProvider {
4460
4473
  iterationsUsed = i + 1;
4461
4474
  const msgTokenEstimate = JSON.stringify(messages).length;
4462
4475
  const sysTokenEstimate = systemPrompt.length;
4463
- console.log(`[Vessel Agent] iteration=${i} messages=${messages.length} msgChars=${msgTokenEstimate} sysChars=${sysTokenEstimate} tools=${tools.length}`);
4464
4476
  const streamStartTime = Date.now();
4465
4477
  const stream = this.client.messages.stream(
4466
4478
  {
@@ -4522,9 +4534,7 @@ class AnthropicProvider {
4522
4534
  } finally {
4523
4535
  if (idleTimer) clearTimeout(idleTimer);
4524
4536
  }
4525
- console.log(`[Vessel Agent] stream complete in ${Date.now() - streamStartTime}ms, toolCalls=${toolUseBlocks.length} textLen=${textContent.length}`);
4526
4537
  const finalMessage = await stream.finalMessage();
4527
- console.log(`[Vessel Agent] finalMessage received, stop_reason=${finalMessage.stop_reason}`);
4528
4538
  const assistantContent = [];
4529
4539
  if (textContent) {
4530
4540
  assistantContent.push({ type: "text", text: textContent });
@@ -4548,19 +4558,43 @@ class AnthropicProvider {
4548
4558
  <<tool:${tb.name}${argSummary ? ":" + argSummary : ""}>>
4549
4559
  `);
4550
4560
  let result;
4551
- const toolStartTime = Date.now();
4552
- console.log(`[Vessel Agent] executing tool: ${tb.name}`);
4553
4561
  try {
4554
4562
  result = await onToolCall(tb.name, tb.input);
4555
4563
  } catch (toolErr) {
4556
- result = `Error: Tool execution failed — ${toolErr.message || toolErr}. Try a different approach or call read_page to refresh context.`;
4564
+ const msg = toolErr instanceof Error ? toolErr.message : String(toolErr);
4565
+ result = `Error: Tool execution failed — ${msg}. Try a different approach or call read_page to refresh context.`;
4566
+ }
4567
+ let parsedRich = null;
4568
+ try {
4569
+ const parsed = JSON.parse(result);
4570
+ if (isRichToolResult(parsed)) parsedRich = parsed;
4571
+ } catch {
4572
+ }
4573
+ if (parsedRich) {
4574
+ toolResults.push({
4575
+ type: "tool_result",
4576
+ tool_use_id: tb.id,
4577
+ content: parsedRich.content.map((block) => {
4578
+ if (block.type === "image") {
4579
+ return {
4580
+ type: "image",
4581
+ source: {
4582
+ type: "base64",
4583
+ media_type: block.mediaType,
4584
+ data: block.base64
4585
+ }
4586
+ };
4587
+ }
4588
+ return { type: "text", text: block.text };
4589
+ })
4590
+ });
4591
+ } else {
4592
+ toolResults.push({
4593
+ type: "tool_result",
4594
+ tool_use_id: tb.id,
4595
+ content: result
4596
+ });
4557
4597
  }
4558
- console.log(`[Vessel Agent] tool ${tb.name} completed in ${Date.now() - toolStartTime}ms, resultLen=${result.length}`);
4559
- toolResults.push({
4560
- type: "tool_result",
4561
- tool_use_id: tb.id,
4562
- content: result
4563
- });
4564
4598
  }
4565
4599
  messages.push({ role: "user", content: toolResults });
4566
4600
  }
@@ -4570,7 +4604,7 @@ class AnthropicProvider {
4570
4604
  [Reached maximum tool call limit (${maxIterations} steps). You can adjust this in Settings → Max Tool Iterations, or continue by sending another message.]`);
4571
4605
  }
4572
4606
  } catch (err) {
4573
- if (err.name !== "AbortError") {
4607
+ if (err instanceof Error && err.name !== "AbortError") {
4574
4608
  onChunk(`
4575
4609
 
4576
4610
  [Error: ${err.message}]`);
@@ -4721,7 +4755,7 @@ class OpenAICompatProvider {
4721
4755
  }
4722
4756
  }
4723
4757
  } catch (err) {
4724
- if (err.name !== "AbortError") {
4758
+ if (err instanceof Error && err.name !== "AbortError") {
4725
4759
  onChunk(`
4726
4760
 
4727
4761
  [Error: ${err.message}]`);
@@ -4745,7 +4779,6 @@ class OpenAICompatProvider {
4745
4779
  for (let i = 0; i < maxIterations; i++) {
4746
4780
  iterationsUsed = i + 1;
4747
4781
  const msgTokenEstimate = JSON.stringify(messages).length;
4748
- console.log(`[Vessel Agent OpenAI] iteration=${i} messages=${messages.length} msgChars=${msgTokenEstimate} tools=${openAITools.length}`);
4749
4782
  const streamStartTime = Date.now();
4750
4783
  let textAccum = "";
4751
4784
  const toolCallAccums = {};
@@ -4781,7 +4814,6 @@ class OpenAICompatProvider {
4781
4814
  }
4782
4815
  }
4783
4816
  }
4784
- console.log(`[Vessel Agent OpenAI] stream complete in ${Date.now() - streamStartTime}ms, toolCalls=${Object.keys(toolCallAccums).length} textLen=${textAccum.length} finishReason=${finishReason}`);
4785
4817
  const toolCalls = Object.values(toolCallAccums);
4786
4818
  for (const tc of Object.values(toolCallAccums)) {
4787
4819
  if (!tc.id) tc.id = `call_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
@@ -4826,18 +4858,24 @@ class OpenAICompatProvider {
4826
4858
  <<tool:${tc.name}${argSummary ? ":" + argSummary : ""}>>
4827
4859
  `);
4828
4860
  let result;
4829
- const toolStartTime = Date.now();
4830
- console.log(`[Vessel Agent OpenAI] executing tool: ${tc.name}`);
4831
4861
  try {
4832
4862
  result = await onToolCall(tc.name, args);
4833
4863
  } catch (toolErr) {
4834
- result = `Error: Tool execution failed — ${toolErr.message || toolErr}. Try a different approach or call read_page to refresh context.`;
4864
+ const msg = toolErr instanceof Error ? toolErr.message : String(toolErr);
4865
+ result = `Error: Tool execution failed — ${msg}. Try a different approach or call read_page to refresh context.`;
4866
+ }
4867
+ let toolContent = result;
4868
+ try {
4869
+ const parsed = JSON.parse(result);
4870
+ if (isRichToolResult(parsed)) {
4871
+ toolContent = parsed.content.filter((b) => b.type === "text").map((b) => b.text).join("\n");
4872
+ }
4873
+ } catch {
4835
4874
  }
4836
- console.log(`[Vessel Agent OpenAI] tool ${tc.name} completed in ${Date.now() - toolStartTime}ms, resultLen=${result.length}`);
4837
4875
  messages.push({
4838
4876
  role: "tool",
4839
4877
  tool_call_id: tc.id,
4840
- content: result
4878
+ content: toolContent
4841
4879
  });
4842
4880
  }
4843
4881
  }
@@ -4847,7 +4885,7 @@ class OpenAICompatProvider {
4847
4885
  [Reached maximum tool call limit (${maxIterations} steps). You can adjust this in Settings → Max Tool Iterations, or continue by sending another message.]`);
4848
4886
  }
4849
4887
  } catch (err) {
4850
- if (err.name !== "AbortError") {
4888
+ if (err instanceof Error && err.name !== "AbortError") {
4851
4889
  onChunk(`
4852
4890
 
4853
4891
  [Error: ${err.message}]`);
@@ -6715,6 +6753,13 @@ const TOOL_DEFINITIONS = [
6715
6753
  },
6716
6754
  tier: 0
6717
6755
  },
6756
+ {
6757
+ name: "screenshot",
6758
+ title: "Screenshot",
6759
+ description: "Take a screenshot of the current page — see exactly what the user sees. Returns the image for visual analysis. Use when you need to verify visual layout, check what's actually rendered on screen, or when text extraction fails on heavy pages.",
6760
+ inputSchema: {},
6761
+ tier: 1
6762
+ },
6718
6763
  {
6719
6764
  name: "wait_for",
6720
6765
  title: "Wait For",
@@ -7150,6 +7195,7 @@ const ALWAYS_FAST_TOOL_NAMES = /* @__PURE__ */ new Set([
7150
7195
  "accept_cookies",
7151
7196
  "wait_for",
7152
7197
  "read_page",
7198
+ "screenshot",
7153
7199
  "inspect_element"
7154
7200
  ]);
7155
7201
  function inferIntent(query) {
@@ -7861,6 +7907,23 @@ function assertSafeURL(url) {
7861
7907
  );
7862
7908
  }
7863
7909
  }
7910
+ async function captureScreenshot(wc) {
7911
+ for (let attempt = 0; attempt < 3; attempt += 1) {
7912
+ await new Promise((resolve) => setTimeout(resolve, 120 * (attempt + 1)));
7913
+ try {
7914
+ const image = await wc.capturePage();
7915
+ if (!image.isEmpty()) {
7916
+ const size = image.getSize();
7917
+ const base64 = image.toPNG().toString("base64");
7918
+ if (base64) {
7919
+ return { ok: true, base64, width: size.width, height: size.height };
7920
+ }
7921
+ }
7922
+ } catch {
7923
+ }
7924
+ }
7925
+ return { ok: false, error: "Page image was empty after 3 attempts" };
7926
+ }
7864
7927
  const SESSION_VERSION = 1;
7865
7928
  function getSessionsDir() {
7866
7929
  return path$1.join(electron.app.getPath("userData"), "named-sessions");
@@ -8308,9 +8371,6 @@ async function executePageScript(wc, script, options) {
8308
8371
  })
8309
8372
  ]);
8310
8373
  if (result === PAGE_SCRIPT_TIMEOUT) {
8311
- console.log(
8312
- `[Vessel pageScript] timed out after ${timeoutMs}ms (${options?.label || "page-script"})`
8313
- );
8314
8374
  return PAGE_SCRIPT_TIMEOUT;
8315
8375
  }
8316
8376
  return result;
@@ -8325,9 +8385,6 @@ async function executePageScript(wc, script, options) {
8325
8385
  function waitForLoad$1(wc, timeout = 5e3) {
8326
8386
  return new Promise((resolve) => {
8327
8387
  let finished = false;
8328
- console.log(
8329
- `[Vessel waitForLoad] started, isLoading=${wc.isLoading()}, timeout=${timeout}`
8330
- );
8331
8388
  const cleanup = () => {
8332
8389
  wc.removeListener("did-finish-load", onLoadEvent);
8333
8390
  wc.removeListener("did-stop-loading", onLoadEvent);
@@ -8336,23 +8393,19 @@ function waitForLoad$1(wc, timeout = 5e3) {
8336
8393
  const finish = (reason) => {
8337
8394
  if (finished) return;
8338
8395
  finished = true;
8339
- console.log(`[Vessel waitForLoad] finished: ${reason}`);
8340
8396
  clearTimeout(timer);
8341
8397
  cleanup();
8342
8398
  resolve();
8343
8399
  };
8344
8400
  const onLoadEvent = () => {
8345
8401
  const loading = wc.isLoading();
8346
- console.log(
8347
- `[Vessel waitForLoad] load event fired, isLoading=${loading}`
8348
- );
8349
8402
  if (!loading) {
8350
- finish("load event");
8403
+ finish();
8351
8404
  }
8352
8405
  };
8353
- const timer = setTimeout(() => finish("timeout"), timeout);
8406
+ const timer = setTimeout(() => finish(), timeout);
8354
8407
  if (!wc.isLoading()) {
8355
- finish("already loaded");
8408
+ finish();
8356
8409
  return;
8357
8410
  }
8358
8411
  wc.on("did-finish-load", onLoadEvent);
@@ -9041,19 +9094,12 @@ ${shadowOverlay}` : result;
9041
9094
  const elInfo = await describeElementForClick$1(wc, selector);
9042
9095
  if ("error" in elInfo) return `Error: ${elInfo.error}`;
9043
9096
  const cartMatch = isAddToCartText(elInfo.text);
9044
- console.log(
9045
- `[Vessel cart-guard] text="${elInfo.text}" cartMatch=${cartMatch} url=${beforeUrl} hasPrior=${recentCartClicks.has(beforeUrl)}`
9046
- );
9047
9097
  if (cartMatch && isDuplicateCartClick(beforeUrl, elInfo.text)) {
9048
- console.log(`[Vessel cart-guard] BLOCKED duplicate add-to-cart click`);
9049
9098
  return `Blocked: "${elInfo.text}" was already clicked on this page. The item is in your cart. Call read_page to see available actions (e.g. View Cart, Continue Shopping).`;
9050
9099
  }
9051
9100
  if (!cartMatch && recentCartClicks.has(beforeUrl)) {
9052
9101
  const dialogActions = await getCartDialogActions$1(wc);
9053
9102
  if (dialogActions) {
9054
- console.log(
9055
- `[Vessel cart-guard] BLOCKED background click while cart dialog is open`
9056
- );
9057
9103
  return `Blocked: a cart confirmation dialog is open. Do not click background elements.
9058
9104
  ${dialogActions}
9059
9105
  Click one of these dialog actions instead.`;
@@ -9066,7 +9112,6 @@ Click one of these dialog actions instead.`;
9066
9112
  }
9067
9113
  }
9068
9114
  if (cartMatch) {
9069
- console.log(`[Vessel cart-guard] RECORDED cart click for url=${beforeUrl}`);
9070
9115
  recordCartClick(beforeUrl, elInfo.text);
9071
9116
  }
9072
9117
  const clickText = `Clicked: ${elInfo.text}`;
@@ -9306,9 +9351,6 @@ async function dismissPopup$1(wc) {
9306
9351
  { timeoutMs: 1500, label: "cart dialog continue shopping" }
9307
9352
  );
9308
9353
  if (continueResult && continueResult !== PAGE_SCRIPT_TIMEOUT && typeof continueResult === "string" && !continueResult.startsWith("Error")) {
9309
- console.log(
9310
- `[Vessel cart-guard] dismiss_popup auto-clicked dialog action: ${continueResult}`
9311
- );
9312
9354
  return `Cart confirmation handled: ${continueResult}. Item was already added to your cart.`;
9313
9355
  }
9314
9356
  const dialogActions = await getCartDialogActions$1(wc);
@@ -10669,6 +10711,7 @@ const KNOWN_TOOLS = /* @__PURE__ */ new Set([
10669
10711
  "dismiss_popup",
10670
10712
  "clear_overlays",
10671
10713
  "read_page",
10714
+ "screenshot",
10672
10715
  "wait_for",
10673
10716
  "create_checkpoint",
10674
10717
  "restore_checkpoint",
@@ -10748,6 +10791,19 @@ async function executeAction(name, args, ctx) {
10748
10791
  dangerous: isDangerousAction$1(name),
10749
10792
  executor: async () => {
10750
10793
  switch (name) {
10794
+ case "screenshot": {
10795
+ if (!wc) return "Error: No active tab";
10796
+ const screenshotStart = Date.now();
10797
+ const shot = await captureScreenshot(wc);
10798
+ if (!shot.ok) return `Error: ${shot.error}`;
10799
+ const screenshotMs = Date.now() - screenshotStart;
10800
+ const title = wc.getTitle() || "(untitled)";
10801
+ const url = wc.getURL();
10802
+ return makeImageResult(
10803
+ shot.base64,
10804
+ `Screenshot of "${title}" (${url}) — ${shot.width}x${shot.height}, captured in ${screenshotMs}ms. Analyze the image to understand the current visual state of the page.`
10805
+ );
10806
+ }
10751
10807
  case "current_tab": {
10752
10808
  const active = ctx.tabManager.getActiveTab();
10753
10809
  const activeId = ctx.tabManager.getActiveTabId();
@@ -10951,14 +11007,12 @@ async function executeAction(name, args, ctx) {
10951
11007
  if (requestedGlance) {
10952
11008
  return glanceExtract(wc);
10953
11009
  }
10954
- console.log("[Vessel read_page] starting extraction with 6s timeout");
10955
11010
  let content = null;
10956
11011
  try {
10957
11012
  content = await Promise.race([
10958
11013
  extractContent(wc),
10959
11014
  new Promise(
10960
11015
  (resolve) => setTimeout(() => {
10961
- console.log("[Vessel read_page] timeout fired, falling back");
10962
11016
  resolve(null);
10963
11017
  }, 6e3)
10964
11018
  )
@@ -10966,18 +11020,13 @@ async function executeAction(name, args, ctx) {
10966
11020
  } catch {
10967
11021
  content = null;
10968
11022
  }
10969
- console.log(
10970
- `[Vessel read_page] extraction result: ${content ? `content=${content.content.length}` : "null (timeout)"}`
10971
- );
10972
11023
  if (!content || content.content.length === 0) {
10973
- console.log("[Vessel read_page] content empty/null, trying quick iframe dismiss");
10974
11024
  try {
10975
11025
  const iframeResult = await Promise.race([
10976
11026
  tryDismissConsentIframe(wc),
10977
11027
  new Promise((resolve) => setTimeout(() => resolve(null), 2e3))
10978
11028
  ]);
10979
11029
  if (iframeResult) {
10980
- console.log(`[Vessel read_page] iframe dismiss: ${iframeResult}`);
10981
11030
  await sleep$1(500);
10982
11031
  try {
10983
11032
  content = await Promise.race([
@@ -11023,7 +11072,6 @@ ${truncated}`;
11023
11072
  `Need more detail? Escalate with read_page(mode="debug") only if the narrow modes are insufficient.`
11024
11073
  ].filter(Boolean).join("\n\n");
11025
11074
  }
11026
- console.log("[Vessel read_page] falling back to glance mode");
11027
11075
  return glanceExtract(wc);
11028
11076
  }
11029
11077
  case "wait_for": {
@@ -11941,11 +11989,7 @@ async function handleAIQuery(query, provider, activeWebContents, onChunk, onEnd,
11941
11989
  const isSummarize = lowerQuery.startsWith("summarize") || lowerQuery.startsWith("tldr") || lowerQuery === "summary";
11942
11990
  if (provider.streamAgentQuery && tabManager && activeWebContents && runtime2) {
11943
11991
  try {
11944
- const extractStart = Date.now();
11945
11992
  const pageContent = await extractContent(activeWebContents);
11946
- console.log(
11947
- `[Vessel Agent] initial extractContent completed in ${Date.now() - extractStart}ms, contentLen=${pageContent.content.length}`
11948
- );
11949
11993
  const pageType = detectPageType(pageContent);
11950
11994
  const defaultReadMode = chooseAgentReadMode(pageContent);
11951
11995
  const structuredContext = buildScopedContext(
@@ -11998,7 +12042,8 @@ Instructions:
11998
12042
  - Escalate page reads progressively: read_page(mode="glance") for a fast viewport snapshot on heavy/slow pages, then read_page(mode="visible_only"), read_page(mode="results_only"), read_page(mode="forms_only"), read_page(mode="summary"), or read_page(mode="text_only") depending on what you need.
11999
12043
  - Use read_page(mode="glance") when a page is slow to load or extraction times out — it shows what's on screen (headings, links, buttons, inputs) without waiting for heavy JS. It's what a human would see by just looking at the page.
12000
12044
  - Use read_page(mode="debug") only as a last resort when the narrower modes are insufficient.
12001
- - If read_page returns empty or times out, do NOT retry with the same mode. Switch to read_page(mode="glance") or interact directly with click/type_text.
12045
+ - If read_page returns empty or times out, do NOT retry with the same mode. Switch to read_page(mode="glance") or use screenshot to see the page visually.
12046
+ - Use screenshot when you need to see exactly what the user sees — visual layout, rendered content, images, or when text extraction is failing. The screenshot returns the actual rendered page image for visual analysis. It works even when the JS thread is completely blocked.
12002
12047
  - VIEWPORT SYNC: Treat scrolling as a real, user-visible browser action. If you say you are going to scroll, call scroll or scroll_to_element so the human sees the page move too.
12003
12048
  - read_page inspects the page without moving the human-visible viewport. Do not describe read_page as scrolling. If you want more context without changing the user's view, say you're reading the page; if you want the user to follow along lower on the page, actually scroll first.
12004
12049
  - After clicking or submitting a form, prefer wait_for on a specific result signal or a narrow read_page mode. Do not jump straight to read_page(mode="debug").
@@ -14215,25 +14260,6 @@ async function waitForCondition(wc, text, selector, timeoutMs) {
14215
14260
  ...diagnostic ? { diagnostic } : {}
14216
14261
  });
14217
14262
  }
14218
- async function captureScreenshotPayload(wc) {
14219
- for (let attempt = 0; attempt < 3; attempt += 1) {
14220
- await new Promise((resolve) => setTimeout(resolve, 120 * (attempt + 1)));
14221
- const image = await wc.capturePage();
14222
- if (!image.isEmpty()) {
14223
- const size = image.getSize();
14224
- const base64 = image.toPNG().toString("base64");
14225
- if (base64) {
14226
- return {
14227
- ok: true,
14228
- base64,
14229
- width: size.width,
14230
- height: size.height
14231
- };
14232
- }
14233
- }
14234
- }
14235
- return { ok: false, error: "page image was empty after 3 attempts" };
14236
- }
14237
14263
  function registerTools(server, tabManager, runtime2) {
14238
14264
  server.registerPrompt(
14239
14265
  "vessel-supervisor-brief",
@@ -15388,7 +15414,7 @@ ${buildScopedContext(pageContent, mode)}`;
15388
15414
  "Error capturing screenshot: active tab has zero-sized bounds"
15389
15415
  );
15390
15416
  }
15391
- const screenshot = await captureScreenshotPayload(tab.view.webContents);
15417
+ const screenshot = await captureScreenshot(tab.view.webContents);
15392
15418
  if (!screenshot.ok) {
15393
15419
  return asTextResponse(
15394
15420
  `Error capturing screenshot: ${screenshot.error}`
@@ -17932,7 +17958,6 @@ ${progress}
17932
17958
  mode: "replace"
17933
17959
  });
17934
17960
  const approvalReason = this.getApprovalReason(dangerous);
17935
- console.log(`[Vessel Runtime] action=${name} dangerous=${dangerous} approvalReason=${approvalReason} mode=${this.state.supervisor.approvalMode}`);
17936
17961
  if (approvalReason) {
17937
17962
  this.publishTranscript({
17938
17963
  source,
@@ -17942,9 +17967,7 @@ ${progress}
17942
17967
  streamId: transcriptStreamId,
17943
17968
  mode: "replace"
17944
17969
  });
17945
- console.log(`[Vessel Runtime] awaiting approval for ${name}...`);
17946
17970
  const approved = await this.awaitApproval(action, approvalReason);
17947
- console.log(`[Vessel Runtime] approval result for ${name}: ${approved}`);
17948
17971
  if (!approved) {
17949
17972
  this.publishTranscript({
17950
17973
  source,
@@ -18125,7 +18148,7 @@ ${progress}
18125
18148
  if (!toolBreakdown[name]) toolBreakdown[name] = { count: 0, totalMs: 0, avgMs: 0, errors: 0 };
18126
18149
  toolBreakdown[name].count++;
18127
18150
  if (action.durationMs != null) toolBreakdown[name].totalMs += action.durationMs;
18128
- if (action.status === "error") toolBreakdown[name].errors++;
18151
+ if (action.status === "failed") toolBreakdown[name].errors++;
18129
18152
  }
18130
18153
  for (const entry of Object.values(toolBreakdown)) {
18131
18154
  entry.avgMs = entry.count > 0 ? Math.round(entry.totalMs / entry.count) : 0;
@@ -1972,7 +1972,7 @@ const _createHooksMap = function _createHooksMap2() {
1972
1972
  function createDOMPurify() {
1973
1973
  let window2 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : getGlobal();
1974
1974
  const DOMPurify = (root2) => createDOMPurify(root2);
1975
- DOMPurify.version = "3.3.2";
1975
+ DOMPurify.version = "3.3.3";
1976
1976
  DOMPurify.removed = [];
1977
1977
  if (!window2 || !window2.document || window2.document.nodeType !== NODE_TYPE.document || !window2.Element) {
1978
1978
  DOMPurify.isSupported = false;
@@ -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-DSaws_sH.js"></script>
8
+ <script type="module" crossorigin src="./assets/index-FJxHleYP.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="./assets/index-DMd-y6tm.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.15",
4
+ "version": "0.1.16",
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": {
@@ -52,22 +52,22 @@
52
52
  },
53
53
  "devDependencies": {
54
54
  "@types/dompurify": "^3.0.5",
55
- "@types/node": "^25.3.5",
56
- "electron": "^40.8.0",
55
+ "@types/node": "^25.5.0",
56
+ "electron": "^40.8.3",
57
57
  "electron-builder": "^26.8.1",
58
58
  "electron-vite": "^5.0.0",
59
59
  "solid-js": "^1.9.11",
60
60
  "tsx": "^4.21.0",
61
61
  "typescript": "^5.9.3",
62
- "vite-plugin-solid": "^2.11.10"
62
+ "vite-plugin-solid": "^2.11.11"
63
63
  },
64
64
  "dependencies": {
65
- "@anthropic-ai/sdk": "^0.78.0",
65
+ "@anthropic-ai/sdk": "^0.80.0",
66
66
  "@modelcontextprotocol/sdk": "^1.27.1",
67
67
  "@mozilla/readability": "^0.6.0",
68
- "dompurify": "^3.3.2",
68
+ "dompurify": "^3.3.3",
69
69
  "linkedom": "^0.18.12",
70
- "openai": "^6.27.0",
70
+ "openai": "^6.32.0",
71
71
  "zod": "^4.3.6"
72
72
  }
73
73
  }