@quanta-intellect/vessel-browser 0.1.25 → 0.1.27
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/README.md +20 -6
- package/out/main/index.js +252 -103
- package/out/preload/index.js +2 -0
- package/out/renderer/assets/{index-BynCvURs.css → index-DP2yMHwF.css} +67 -0
- package/out/renderer/assets/{index-32axMD1q.js → index-v71lXiVB.js} +656 -458
- package/out/renderer/index.html +2 -2
- package/package.json +1 -1
package/out/main/index.js
CHANGED
|
@@ -2450,6 +2450,7 @@ const Channels = {
|
|
|
2450
2450
|
PREMIUM_CHECKOUT: "premium:checkout",
|
|
2451
2451
|
PREMIUM_PORTAL: "premium:portal",
|
|
2452
2452
|
PREMIUM_RESET: "premium:reset",
|
|
2453
|
+
PREMIUM_TRACK_CONTEXT: "premium:track-context",
|
|
2453
2454
|
PREMIUM_UPDATE: "premium:update",
|
|
2454
2455
|
// Agent Credential Vault
|
|
2455
2456
|
VAULT_LIST: "vault:list",
|
|
@@ -3471,6 +3472,9 @@ function stopBackgroundRevalidation() {
|
|
|
3471
3472
|
revalidationTimer = null;
|
|
3472
3473
|
}
|
|
3473
3474
|
}
|
|
3475
|
+
function isPremiumActiveState(state2) {
|
|
3476
|
+
return state2.status === "active" || state2.status === "trialing";
|
|
3477
|
+
}
|
|
3474
3478
|
const POSTHOG_API_KEY = process.env.POSTHOG_API_KEY || "phc_OMeM3P5cxJwl14lOKxYad0Yre52xvjNfkLEFnPtXyM";
|
|
3475
3479
|
const POSTHOG_HOST = process.env.POSTHOG_HOST || "https://us.i.posthog.com";
|
|
3476
3480
|
const BATCH_INTERVAL_MS = 6e4;
|
|
@@ -13743,6 +13747,69 @@ async function requestConsent(request) {
|
|
|
13743
13747
|
}
|
|
13744
13748
|
let httpServer = null;
|
|
13745
13749
|
let mcpAuthToken = null;
|
|
13750
|
+
const MCP_AUTH_FILENAME = "mcp-auth.json";
|
|
13751
|
+
function getMcpAuthFilePath() {
|
|
13752
|
+
const configDir = process.env.VESSEL_CONFIG_DIR || path$1.join(
|
|
13753
|
+
process.env.XDG_CONFIG_HOME || path$1.join(os.homedir(), ".config"),
|
|
13754
|
+
"vessel"
|
|
13755
|
+
);
|
|
13756
|
+
return path$1.join(configDir, MCP_AUTH_FILENAME);
|
|
13757
|
+
}
|
|
13758
|
+
function readMcpAuthFile() {
|
|
13759
|
+
try {
|
|
13760
|
+
const raw = fs$1.readFileSync(getMcpAuthFilePath(), "utf8");
|
|
13761
|
+
const parsed = JSON.parse(raw);
|
|
13762
|
+
return parsed && typeof parsed === "object" ? parsed : null;
|
|
13763
|
+
} catch {
|
|
13764
|
+
return null;
|
|
13765
|
+
}
|
|
13766
|
+
}
|
|
13767
|
+
const MIN_TOKEN_LENGTH = 32;
|
|
13768
|
+
function getPersistentMcpAuthToken() {
|
|
13769
|
+
const existingToken = readMcpAuthFile()?.token?.trim();
|
|
13770
|
+
if (existingToken && existingToken.length >= MIN_TOKEN_LENGTH) {
|
|
13771
|
+
return existingToken;
|
|
13772
|
+
}
|
|
13773
|
+
return crypto$2.randomBytes(32).toString("hex");
|
|
13774
|
+
}
|
|
13775
|
+
function writeMcpAuthFile(endpoint, token) {
|
|
13776
|
+
try {
|
|
13777
|
+
const filePath = getMcpAuthFilePath();
|
|
13778
|
+
fs$1.mkdirSync(path$1.dirname(filePath), { recursive: true });
|
|
13779
|
+
fs$1.writeFileSync(
|
|
13780
|
+
filePath,
|
|
13781
|
+
JSON.stringify({ endpoint, token, pid: process.pid }, null, 2) + "\n",
|
|
13782
|
+
{ mode: 384 }
|
|
13783
|
+
);
|
|
13784
|
+
} catch (err) {
|
|
13785
|
+
console.warn("[Vessel MCP] Failed to write auth file:", err);
|
|
13786
|
+
}
|
|
13787
|
+
}
|
|
13788
|
+
function clearMcpAuthFile() {
|
|
13789
|
+
const existingToken = readMcpAuthFile()?.token?.trim();
|
|
13790
|
+
if (!existingToken) {
|
|
13791
|
+
try {
|
|
13792
|
+
fs$1.unlinkSync(getMcpAuthFilePath());
|
|
13793
|
+
} catch {
|
|
13794
|
+
}
|
|
13795
|
+
return;
|
|
13796
|
+
}
|
|
13797
|
+
try {
|
|
13798
|
+
const filePath = getMcpAuthFilePath();
|
|
13799
|
+
fs$1.mkdirSync(path$1.dirname(filePath), { recursive: true });
|
|
13800
|
+
fs$1.writeFileSync(
|
|
13801
|
+
filePath,
|
|
13802
|
+
JSON.stringify(
|
|
13803
|
+
{ endpoint: "", token: existingToken, pid: null },
|
|
13804
|
+
null,
|
|
13805
|
+
2
|
|
13806
|
+
) + "\n",
|
|
13807
|
+
{ mode: 384 }
|
|
13808
|
+
);
|
|
13809
|
+
} catch (err) {
|
|
13810
|
+
console.warn("[Vessel MCP] Failed to clear auth file:", err);
|
|
13811
|
+
}
|
|
13812
|
+
}
|
|
13746
13813
|
function asTextResponse(text) {
|
|
13747
13814
|
return { content: [{ type: "text", text }] };
|
|
13748
13815
|
}
|
|
@@ -15198,7 +15265,7 @@ function registerTools(server, tabManager, runtime2) {
|
|
|
15198
15265
|
else if (tier === 1) score = 30;
|
|
15199
15266
|
else score = 40;
|
|
15200
15267
|
return {
|
|
15201
|
-
name:
|
|
15268
|
+
name: def.name,
|
|
15202
15269
|
title: def.title,
|
|
15203
15270
|
description: def.description,
|
|
15204
15271
|
tier,
|
|
@@ -15230,10 +15297,10 @@ function registerTools(server, tabManager, runtime2) {
|
|
|
15230
15297
|
}
|
|
15231
15298
|
);
|
|
15232
15299
|
server.registerTool(
|
|
15233
|
-
"
|
|
15300
|
+
"current_tab",
|
|
15234
15301
|
{
|
|
15235
15302
|
title: "Get Active Tab",
|
|
15236
|
-
description: "Return the browser tab the human is actively looking at right now. Use this instead of
|
|
15303
|
+
description: "Return the browser tab the human is actively looking at right now. Use this instead of list_tabs when you only need the focused tab."
|
|
15237
15304
|
},
|
|
15238
15305
|
async () => {
|
|
15239
15306
|
const activeTab = getActiveTabSummary(tabManager);
|
|
@@ -15242,7 +15309,7 @@ function registerTools(server, tabManager, runtime2) {
|
|
|
15242
15309
|
}
|
|
15243
15310
|
);
|
|
15244
15311
|
server.registerTool(
|
|
15245
|
-
"
|
|
15312
|
+
"publish_transcript",
|
|
15246
15313
|
{
|
|
15247
15314
|
title: "Publish Agent Transcript",
|
|
15248
15315
|
description: "Publish or stream agent reasoning/status text into Vessel's in-browser transcript monitor. Intended for external harnesses that want to mirror live thinking into the browser UI.",
|
|
@@ -15283,7 +15350,7 @@ function registerTools(server, tabManager, runtime2) {
|
|
|
15283
15350
|
}
|
|
15284
15351
|
);
|
|
15285
15352
|
server.registerTool(
|
|
15286
|
-
"
|
|
15353
|
+
"clear_transcript",
|
|
15287
15354
|
{
|
|
15288
15355
|
title: "Clear Agent Transcript",
|
|
15289
15356
|
description: "Clear the in-browser transcript monitor state."
|
|
@@ -15334,7 +15401,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15334
15401
|
${buildScopedContext(pageContent, mode)}`;
|
|
15335
15402
|
}
|
|
15336
15403
|
server.registerTool(
|
|
15337
|
-
"
|
|
15404
|
+
"extract_content",
|
|
15338
15405
|
{
|
|
15339
15406
|
title: "Extract Page Content",
|
|
15340
15407
|
description: "Extract structured content from the current page. Modes: 'full' (default, everything), 'summary' (title+headings+stats), 'interactives_only' (clickable elements with indices), 'forms_only' (form fields only), 'text_only' (page text, no interactives), 'visible_only' (only currently visible, in-viewport, unobstructed elements plus active overlays), 'results_only' (likely primary search/result links only).",
|
|
@@ -15366,7 +15433,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15366
15433
|
}
|
|
15367
15434
|
);
|
|
15368
15435
|
server.registerTool(
|
|
15369
|
-
"
|
|
15436
|
+
"read_page",
|
|
15370
15437
|
{
|
|
15371
15438
|
title: "Read Page",
|
|
15372
15439
|
description: "Read the active tab's page content. Includes saved highlights plus any active text selection or visible unsaved highlights on the page. Supports modes: full (default — includes highlights section), summary, interactives_only, forms_only, text_only, visible_only, results_only.",
|
|
@@ -15398,7 +15465,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15398
15465
|
}
|
|
15399
15466
|
);
|
|
15400
15467
|
server.registerTool(
|
|
15401
|
-
"
|
|
15468
|
+
"list_tabs",
|
|
15402
15469
|
{
|
|
15403
15470
|
title: "List Tabs",
|
|
15404
15471
|
description: "List all open browser tabs with their IDs, titles, and URLs."
|
|
@@ -15414,7 +15481,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15414
15481
|
}
|
|
15415
15482
|
);
|
|
15416
15483
|
server.registerTool(
|
|
15417
|
-
"
|
|
15484
|
+
"navigate",
|
|
15418
15485
|
{
|
|
15419
15486
|
title: "Navigate",
|
|
15420
15487
|
description: "Navigate the active browser tab to a URL. Use postBody to submit data via POST request (e.g. form submissions).",
|
|
@@ -15455,7 +15522,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15455
15522
|
}
|
|
15456
15523
|
);
|
|
15457
15524
|
server.registerTool(
|
|
15458
|
-
"
|
|
15525
|
+
"set_ad_blocking",
|
|
15459
15526
|
{
|
|
15460
15527
|
title: "Set Ad Blocking",
|
|
15461
15528
|
description: "Enable or disable ad blocking for the active tab or a matched tab. Reload after changes unless reload is false.",
|
|
@@ -15500,7 +15567,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15500
15567
|
}
|
|
15501
15568
|
);
|
|
15502
15569
|
server.registerTool(
|
|
15503
|
-
"
|
|
15570
|
+
"extract_structured_data",
|
|
15504
15571
|
{
|
|
15505
15572
|
title: "Extract Structured Data",
|
|
15506
15573
|
description: "Return normalized structured data derived from page JSON-LD, microdata, RDFa, and high-signal meta tags. Useful for recipes, products, articles, events, FAQs, and other schema-rich pages.",
|
|
@@ -15553,7 +15620,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15553
15620
|
}
|
|
15554
15621
|
);
|
|
15555
15622
|
server.registerTool(
|
|
15556
|
-
"
|
|
15623
|
+
"go_back",
|
|
15557
15624
|
{
|
|
15558
15625
|
title: "Go Back",
|
|
15559
15626
|
description: "Go back in browser history."
|
|
@@ -15574,7 +15641,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15574
15641
|
}
|
|
15575
15642
|
);
|
|
15576
15643
|
server.registerTool(
|
|
15577
|
-
"
|
|
15644
|
+
"go_forward",
|
|
15578
15645
|
{
|
|
15579
15646
|
title: "Go Forward",
|
|
15580
15647
|
description: "Go forward in browser history."
|
|
@@ -15595,7 +15662,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15595
15662
|
}
|
|
15596
15663
|
);
|
|
15597
15664
|
server.registerTool(
|
|
15598
|
-
"
|
|
15665
|
+
"reload",
|
|
15599
15666
|
{
|
|
15600
15667
|
title: "Reload",
|
|
15601
15668
|
description: "Reload the current page."
|
|
@@ -15611,7 +15678,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15611
15678
|
}
|
|
15612
15679
|
);
|
|
15613
15680
|
server.registerTool(
|
|
15614
|
-
"
|
|
15681
|
+
"click",
|
|
15615
15682
|
{
|
|
15616
15683
|
title: "Click Element",
|
|
15617
15684
|
description: "Click an element on the page by its index number or CSS selector.",
|
|
@@ -15640,7 +15707,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15640
15707
|
}
|
|
15641
15708
|
);
|
|
15642
15709
|
server.registerTool(
|
|
15643
|
-
"
|
|
15710
|
+
"hover",
|
|
15644
15711
|
{
|
|
15645
15712
|
title: "Hover Element",
|
|
15646
15713
|
description: "Move the mouse pointer over an element to trigger hover states, tooltips, or dropdown menus.",
|
|
@@ -15669,7 +15736,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15669
15736
|
}
|
|
15670
15737
|
);
|
|
15671
15738
|
server.registerTool(
|
|
15672
|
-
"
|
|
15739
|
+
"focus",
|
|
15673
15740
|
{
|
|
15674
15741
|
title: "Focus Element",
|
|
15675
15742
|
description: "Focus an input, button, or interactive element. Useful before pressing keys or to trigger focus-dependent UI.",
|
|
@@ -15698,7 +15765,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15698
15765
|
}
|
|
15699
15766
|
);
|
|
15700
15767
|
server.registerTool(
|
|
15701
|
-
"
|
|
15768
|
+
"extract_text",
|
|
15702
15769
|
{
|
|
15703
15770
|
title: "Extract Element Text",
|
|
15704
15771
|
description: "Extract the text content of a specific element by its index number or CSS selector.",
|
|
@@ -15779,7 +15846,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15779
15846
|
}
|
|
15780
15847
|
);
|
|
15781
15848
|
server.registerTool(
|
|
15782
|
-
"
|
|
15849
|
+
"type",
|
|
15783
15850
|
{
|
|
15784
15851
|
title: "Type Text",
|
|
15785
15852
|
description: "Type text into an input field or textarea. Clears existing content first.",
|
|
@@ -15818,10 +15885,10 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15818
15885
|
}
|
|
15819
15886
|
);
|
|
15820
15887
|
server.registerTool(
|
|
15821
|
-
"
|
|
15888
|
+
"type_text",
|
|
15822
15889
|
{
|
|
15823
15890
|
title: "Type Text",
|
|
15824
|
-
description: "Alias for
|
|
15891
|
+
description: "Alias for type. Type text into an input field or textarea.",
|
|
15825
15892
|
inputSchema: {
|
|
15826
15893
|
index: zod.z.number().optional().describe("Element index from the page content listing"),
|
|
15827
15894
|
selector: zod.z.string().optional().describe("CSS selector as fallback"),
|
|
@@ -15857,7 +15924,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15857
15924
|
}
|
|
15858
15925
|
);
|
|
15859
15926
|
server.registerTool(
|
|
15860
|
-
"
|
|
15927
|
+
"select_option",
|
|
15861
15928
|
{
|
|
15862
15929
|
title: "Select Option",
|
|
15863
15930
|
description: "Select an option in a dropdown by label or value.",
|
|
@@ -15881,7 +15948,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15881
15948
|
}
|
|
15882
15949
|
);
|
|
15883
15950
|
server.registerTool(
|
|
15884
|
-
"
|
|
15951
|
+
"submit_form",
|
|
15885
15952
|
{
|
|
15886
15953
|
title: "Submit Form",
|
|
15887
15954
|
description: "Submit a form using a field index, submit button index, form selector, or button selector.",
|
|
@@ -15913,7 +15980,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15913
15980
|
}
|
|
15914
15981
|
);
|
|
15915
15982
|
server.registerTool(
|
|
15916
|
-
"
|
|
15983
|
+
"press_key",
|
|
15917
15984
|
{
|
|
15918
15985
|
title: "Press Key",
|
|
15919
15986
|
description: "Press a keyboard key, optionally after focusing an element.",
|
|
@@ -15948,7 +16015,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15948
16015
|
}
|
|
15949
16016
|
);
|
|
15950
16017
|
server.registerTool(
|
|
15951
|
-
"
|
|
16018
|
+
"scroll",
|
|
15952
16019
|
{
|
|
15953
16020
|
title: "Scroll Page",
|
|
15954
16021
|
description: "Scroll the page up or down.",
|
|
@@ -15977,7 +16044,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15977
16044
|
}
|
|
15978
16045
|
);
|
|
15979
16046
|
server.registerTool(
|
|
15980
|
-
"
|
|
16047
|
+
"dismiss_popup",
|
|
15981
16048
|
{
|
|
15982
16049
|
title: "Dismiss Popup",
|
|
15983
16050
|
description: "Dismiss a modal, popup, newsletter gate, cookie banner, or blocking overlay using common close and decline actions."
|
|
@@ -15995,7 +16062,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15995
16062
|
}
|
|
15996
16063
|
);
|
|
15997
16064
|
server.registerTool(
|
|
15998
|
-
"
|
|
16065
|
+
"clear_overlays",
|
|
15999
16066
|
{
|
|
16000
16067
|
title: "Clear Overlays",
|
|
16001
16068
|
description: "Work through blocking overlays and modals until the page is unblocked, using overlay-specific heuristics for consent banners and radio-selection dialogs.",
|
|
@@ -16021,7 +16088,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
16021
16088
|
}
|
|
16022
16089
|
);
|
|
16023
16090
|
server.registerTool(
|
|
16024
|
-
"
|
|
16091
|
+
"wait_for",
|
|
16025
16092
|
{
|
|
16026
16093
|
title: "Wait For",
|
|
16027
16094
|
description: "Wait for text or a selector to appear on the current page.",
|
|
@@ -16044,7 +16111,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
16044
16111
|
}
|
|
16045
16112
|
);
|
|
16046
16113
|
server.registerTool(
|
|
16047
|
-
"
|
|
16114
|
+
"create_tab",
|
|
16048
16115
|
{
|
|
16049
16116
|
title: "Create Tab",
|
|
16050
16117
|
description: "Open a new browser tab, optionally navigating to a URL.",
|
|
@@ -16062,7 +16129,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
16062
16129
|
})
|
|
16063
16130
|
);
|
|
16064
16131
|
server.registerTool(
|
|
16065
|
-
"
|
|
16132
|
+
"switch_tab",
|
|
16066
16133
|
{
|
|
16067
16134
|
title: "Switch Tab",
|
|
16068
16135
|
description: "Switch to a different browser tab by ID or title/URL match.",
|
|
@@ -16087,7 +16154,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
16087
16154
|
)
|
|
16088
16155
|
);
|
|
16089
16156
|
server.registerTool(
|
|
16090
|
-
"
|
|
16157
|
+
"close_tab",
|
|
16091
16158
|
{
|
|
16092
16159
|
title: "Close Tab",
|
|
16093
16160
|
description: "Close a browser tab by its ID.",
|
|
@@ -16101,7 +16168,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
16101
16168
|
})
|
|
16102
16169
|
);
|
|
16103
16170
|
server.registerTool(
|
|
16104
|
-
"
|
|
16171
|
+
"checkpoint_create",
|
|
16105
16172
|
{
|
|
16106
16173
|
title: "Create Checkpoint",
|
|
16107
16174
|
description: "Capture the current session as a named checkpoint.",
|
|
@@ -16122,7 +16189,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
16122
16189
|
)
|
|
16123
16190
|
);
|
|
16124
16191
|
server.registerTool(
|
|
16125
|
-
"
|
|
16192
|
+
"checkpoint_restore",
|
|
16126
16193
|
{
|
|
16127
16194
|
title: "Restore Checkpoint",
|
|
16128
16195
|
description: "Restore a saved checkpoint by ID or exact name.",
|
|
@@ -16148,7 +16215,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
16148
16215
|
)
|
|
16149
16216
|
);
|
|
16150
16217
|
server.registerTool(
|
|
16151
|
-
"
|
|
16218
|
+
"save_session",
|
|
16152
16219
|
{
|
|
16153
16220
|
title: "Save Session",
|
|
16154
16221
|
description: "Persist the current cookies, localStorage, and tab layout under a reusable session name.",
|
|
@@ -16165,7 +16232,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
16165
16232
|
})
|
|
16166
16233
|
);
|
|
16167
16234
|
server.registerTool(
|
|
16168
|
-
"
|
|
16235
|
+
"load_session",
|
|
16169
16236
|
{
|
|
16170
16237
|
title: "Load Session",
|
|
16171
16238
|
description: "Load a previously saved named session, restoring cookies, localStorage, and saved tabs.",
|
|
@@ -16182,7 +16249,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
16182
16249
|
})
|
|
16183
16250
|
);
|
|
16184
16251
|
server.registerTool(
|
|
16185
|
-
"
|
|
16252
|
+
"list_sessions",
|
|
16186
16253
|
{
|
|
16187
16254
|
title: "List Sessions",
|
|
16188
16255
|
description: "List previously saved named browser sessions with cookie and storage counts."
|
|
@@ -16196,7 +16263,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
16196
16263
|
})
|
|
16197
16264
|
);
|
|
16198
16265
|
server.registerTool(
|
|
16199
|
-
"
|
|
16266
|
+
"delete_session",
|
|
16200
16267
|
{
|
|
16201
16268
|
title: "Delete Session",
|
|
16202
16269
|
description: "Delete a previously saved named browser session.",
|
|
@@ -16213,7 +16280,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
16213
16280
|
)
|
|
16214
16281
|
);
|
|
16215
16282
|
server.registerTool(
|
|
16216
|
-
"
|
|
16283
|
+
"screenshot",
|
|
16217
16284
|
{
|
|
16218
16285
|
title: "Screenshot",
|
|
16219
16286
|
description: "Capture a screenshot of the current page. Returns a base64-encoded PNG image."
|
|
@@ -16265,7 +16332,7 @@ To analyze visually, call vision_analyze with image_url="${screenshotPath}"`
|
|
|
16265
16332
|
}
|
|
16266
16333
|
);
|
|
16267
16334
|
server.registerTool(
|
|
16268
|
-
"
|
|
16335
|
+
"highlight",
|
|
16269
16336
|
{
|
|
16270
16337
|
title: "Highlight Element",
|
|
16271
16338
|
description: "Visually highlight an element or text on the page for the user. Use to draw attention to specific parts of the page. Highlights persist until cleared. Set persist=true to save the highlight so it re-appears when the user revisits this page.",
|
|
@@ -16332,7 +16399,7 @@ To analyze visually, call vision_analyze with image_url="${screenshotPath}"`
|
|
|
16332
16399
|
}
|
|
16333
16400
|
);
|
|
16334
16401
|
server.registerTool(
|
|
16335
|
-
"
|
|
16402
|
+
"clear_highlights",
|
|
16336
16403
|
{
|
|
16337
16404
|
title: "Clear Highlights",
|
|
16338
16405
|
description: "Remove all visual highlights from the current page, including any saved persistent highlights for this URL."
|
|
@@ -16355,7 +16422,7 @@ To analyze visually, call vision_analyze with image_url="${screenshotPath}"`
|
|
|
16355
16422
|
}
|
|
16356
16423
|
);
|
|
16357
16424
|
server.registerTool(
|
|
16358
|
-
"
|
|
16425
|
+
"list_highlights",
|
|
16359
16426
|
{
|
|
16360
16427
|
title: "List Highlights",
|
|
16361
16428
|
description: "List highlights related to the current browsing session. Includes saved persistent highlights plus the active tab's live text selection and any visible unsaved highlight marks. IMPORTANT: When the user says they highlighted or selected text, call this tool before falling back to screenshots or vision.",
|
|
@@ -16447,10 +16514,10 @@ ${JSON.stringify(otherHighlights, null, 2)}`
|
|
|
16447
16514
|
}
|
|
16448
16515
|
);
|
|
16449
16516
|
server.registerTool(
|
|
16450
|
-
"
|
|
16517
|
+
"remove_highlight",
|
|
16451
16518
|
{
|
|
16452
16519
|
title: "Remove Persistent Highlight",
|
|
16453
|
-
description: "Remove a persistent highlight by ID and clear it from any open tab. Use
|
|
16520
|
+
description: "Remove a persistent highlight by ID and clear it from any open tab. Use list_highlights to find IDs.",
|
|
16454
16521
|
inputSchema: {
|
|
16455
16522
|
id: zod.z.string().describe("ID of the highlight to remove")
|
|
16456
16523
|
}
|
|
@@ -16486,7 +16553,7 @@ ${JSON.stringify(otherHighlights, null, 2)}`
|
|
|
16486
16553
|
}
|
|
16487
16554
|
);
|
|
16488
16555
|
server.registerTool(
|
|
16489
|
-
"
|
|
16556
|
+
"create_folder",
|
|
16490
16557
|
{
|
|
16491
16558
|
title: "Create Bookmark Folder",
|
|
16492
16559
|
description: "Create a named folder for organizing bookmarks. If a folder with the same name already exists, return it instead of duplicating it.",
|
|
@@ -16517,7 +16584,7 @@ ${JSON.stringify(otherHighlights, null, 2)}`
|
|
|
16517
16584
|
}
|
|
16518
16585
|
);
|
|
16519
16586
|
server.registerTool(
|
|
16520
|
-
"
|
|
16587
|
+
"bookmark_save",
|
|
16521
16588
|
{
|
|
16522
16589
|
title: "Save Bookmark",
|
|
16523
16590
|
description: "Save the current page, a specific URL, or a link target from the current page into a bookmark folder. You can provide folder_id or folder_name; missing folder names can be created automatically.",
|
|
@@ -16627,7 +16694,7 @@ ${JSON.stringify(otherHighlights, null, 2)}`
|
|
|
16627
16694
|
}
|
|
16628
16695
|
);
|
|
16629
16696
|
server.registerTool(
|
|
16630
|
-
"
|
|
16697
|
+
"bookmark_list",
|
|
16631
16698
|
{
|
|
16632
16699
|
title: "List Bookmarks",
|
|
16633
16700
|
description: "List all bookmark folders and their contents. Optionally filter by folder.",
|
|
@@ -16677,7 +16744,7 @@ ${JSON.stringify(otherHighlights, null, 2)}`
|
|
|
16677
16744
|
}
|
|
16678
16745
|
);
|
|
16679
16746
|
server.registerTool(
|
|
16680
|
-
"
|
|
16747
|
+
"bookmark_organize",
|
|
16681
16748
|
{
|
|
16682
16749
|
title: "Organize Bookmark",
|
|
16683
16750
|
description: "Organize a bookmark by intent: save or move a bookmark into a folder, creating the folder if needed. Works with bookmark_id, url, a link target from the current page, or the current page itself.",
|
|
@@ -16760,7 +16827,7 @@ ${JSON.stringify(otherHighlights, null, 2)}`
|
|
|
16760
16827
|
}
|
|
16761
16828
|
);
|
|
16762
16829
|
server.registerTool(
|
|
16763
|
-
"
|
|
16830
|
+
"bookmark_search",
|
|
16764
16831
|
{
|
|
16765
16832
|
title: "Search Bookmarks",
|
|
16766
16833
|
description: "Search bookmarks by title, URL, note, folder name, or folder summary.",
|
|
@@ -16791,7 +16858,7 @@ ${JSON.stringify(otherHighlights, null, 2)}`
|
|
|
16791
16858
|
}
|
|
16792
16859
|
);
|
|
16793
16860
|
server.registerTool(
|
|
16794
|
-
"
|
|
16861
|
+
"bookmark_remove",
|
|
16795
16862
|
{
|
|
16796
16863
|
title: "Remove Bookmark",
|
|
16797
16864
|
description: "Remove a specific bookmark by its ID.",
|
|
@@ -16813,7 +16880,7 @@ ${JSON.stringify(otherHighlights, null, 2)}`
|
|
|
16813
16880
|
}
|
|
16814
16881
|
);
|
|
16815
16882
|
server.registerTool(
|
|
16816
|
-
"
|
|
16883
|
+
"bookmark_archive",
|
|
16817
16884
|
{
|
|
16818
16885
|
title: "Archive Bookmark",
|
|
16819
16886
|
description: 'Archive the current page, a URL, a link target from the current page, or an existing bookmark into the default "Archive" folder.',
|
|
@@ -16893,7 +16960,7 @@ ${JSON.stringify(otherHighlights, null, 2)}`
|
|
|
16893
16960
|
}
|
|
16894
16961
|
);
|
|
16895
16962
|
server.registerTool(
|
|
16896
|
-
"
|
|
16963
|
+
"bookmark_open",
|
|
16897
16964
|
{
|
|
16898
16965
|
title: "Open Bookmark",
|
|
16899
16966
|
description: "Open a saved bookmark by bookmark ID. Optionally open it in a new tab.",
|
|
@@ -16937,7 +17004,7 @@ ${JSON.stringify(otherHighlights, null, 2)}`
|
|
|
16937
17004
|
}
|
|
16938
17005
|
);
|
|
16939
17006
|
server.registerTool(
|
|
16940
|
-
"
|
|
17007
|
+
"folder_remove",
|
|
16941
17008
|
{
|
|
16942
17009
|
title: "Remove Bookmark Folder",
|
|
16943
17010
|
description: "Remove a folder. Bookmarks in it are moved to Unsorted.",
|
|
@@ -16961,7 +17028,7 @@ ${JSON.stringify(otherHighlights, null, 2)}`
|
|
|
16961
17028
|
}
|
|
16962
17029
|
);
|
|
16963
17030
|
server.registerTool(
|
|
16964
|
-
"
|
|
17031
|
+
"folder_rename",
|
|
16965
17032
|
{
|
|
16966
17033
|
title: "Rename Bookmark Folder",
|
|
16967
17034
|
description: "Rename an existing bookmark folder.",
|
|
@@ -16995,7 +17062,7 @@ ${JSON.stringify(otherHighlights, null, 2)}`
|
|
|
16995
17062
|
}
|
|
16996
17063
|
);
|
|
16997
17064
|
server.registerTool(
|
|
16998
|
-
"
|
|
17065
|
+
"memory_note_create",
|
|
16999
17066
|
{
|
|
17000
17067
|
title: "Create Memory Note",
|
|
17001
17068
|
description: "Write a markdown note into the configured Obsidian vault for research notes, breadcrumbs, or synthesis.",
|
|
@@ -17022,7 +17089,7 @@ ${JSON.stringify(otherHighlights, null, 2)}`
|
|
|
17022
17089
|
}
|
|
17023
17090
|
);
|
|
17024
17091
|
server.registerTool(
|
|
17025
|
-
"
|
|
17092
|
+
"memory_append",
|
|
17026
17093
|
{
|
|
17027
17094
|
title: "Append Memory Note",
|
|
17028
17095
|
description: "Append markdown content to an existing note in the configured Obsidian vault.",
|
|
@@ -17050,7 +17117,7 @@ ${JSON.stringify(otherHighlights, null, 2)}`
|
|
|
17050
17117
|
}
|
|
17051
17118
|
);
|
|
17052
17119
|
server.registerTool(
|
|
17053
|
-
"
|
|
17120
|
+
"memory_list",
|
|
17054
17121
|
{
|
|
17055
17122
|
title: "List Memory Notes",
|
|
17056
17123
|
description: "List recent markdown notes in the configured Obsidian vault.",
|
|
@@ -17078,7 +17145,7 @@ ${JSON.stringify(otherHighlights, null, 2)}`
|
|
|
17078
17145
|
}
|
|
17079
17146
|
);
|
|
17080
17147
|
server.registerTool(
|
|
17081
|
-
"
|
|
17148
|
+
"memory_search",
|
|
17082
17149
|
{
|
|
17083
17150
|
title: "Search Memory Notes",
|
|
17084
17151
|
description: "Search markdown notes in the configured Obsidian vault by title, path, body, and optional tags.",
|
|
@@ -17108,7 +17175,7 @@ ${JSON.stringify(otherHighlights, null, 2)}`
|
|
|
17108
17175
|
}
|
|
17109
17176
|
);
|
|
17110
17177
|
server.registerTool(
|
|
17111
|
-
"
|
|
17178
|
+
"memory_page_capture",
|
|
17112
17179
|
{
|
|
17113
17180
|
title: "Capture Page To Memory",
|
|
17114
17181
|
description: "Capture the current page into the configured Obsidian vault as a markdown note with URL, excerpt, and content snapshot.",
|
|
@@ -17144,7 +17211,7 @@ ${JSON.stringify(otherHighlights, null, 2)}`
|
|
|
17144
17211
|
}
|
|
17145
17212
|
);
|
|
17146
17213
|
server.registerTool(
|
|
17147
|
-
"
|
|
17214
|
+
"memory_link_bookmark",
|
|
17148
17215
|
{
|
|
17149
17216
|
title: "Link Bookmark To Memory",
|
|
17150
17217
|
description: "Create a note for a bookmark or append bookmark details into an existing memory note.",
|
|
@@ -17184,7 +17251,7 @@ ${JSON.stringify(otherHighlights, null, 2)}`
|
|
|
17184
17251
|
}
|
|
17185
17252
|
);
|
|
17186
17253
|
server.registerTool(
|
|
17187
|
-
"
|
|
17254
|
+
"flow_start",
|
|
17188
17255
|
{
|
|
17189
17256
|
title: "Start Workflow",
|
|
17190
17257
|
description: "Begin tracking a multi-step web workflow. Vessel will show progress after every action so you always know where you are in the flow.",
|
|
@@ -17212,7 +17279,7 @@ ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`
|
|
|
17212
17279
|
}
|
|
17213
17280
|
);
|
|
17214
17281
|
server.registerTool(
|
|
17215
|
-
"
|
|
17282
|
+
"flow_advance",
|
|
17216
17283
|
{
|
|
17217
17284
|
title: "Advance Workflow Step",
|
|
17218
17285
|
description: "Mark the current workflow step as done and move to the next one. Call this after completing each step.",
|
|
@@ -17228,7 +17295,7 @@ ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`
|
|
|
17228
17295
|
}
|
|
17229
17296
|
);
|
|
17230
17297
|
server.registerTool(
|
|
17231
|
-
"
|
|
17298
|
+
"flow_status",
|
|
17232
17299
|
{
|
|
17233
17300
|
title: "Workflow Status",
|
|
17234
17301
|
description: "Check the current workflow progress."
|
|
@@ -17240,7 +17307,7 @@ ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`
|
|
|
17240
17307
|
}
|
|
17241
17308
|
);
|
|
17242
17309
|
server.registerTool(
|
|
17243
|
-
"
|
|
17310
|
+
"flow_end",
|
|
17244
17311
|
{
|
|
17245
17312
|
title: "End Workflow",
|
|
17246
17313
|
description: "Clear the active workflow tracker."
|
|
@@ -17251,7 +17318,7 @@ ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`
|
|
|
17251
17318
|
}
|
|
17252
17319
|
);
|
|
17253
17320
|
server.registerTool(
|
|
17254
|
-
"
|
|
17321
|
+
"suggest",
|
|
17255
17322
|
{
|
|
17256
17323
|
title: "What Should I Do?",
|
|
17257
17324
|
description: "Analyze the current page and return the most relevant tools and suggested next actions. Call this when you're unsure what to do next — it reads the page context and tells you the optimal approach."
|
|
@@ -17260,7 +17327,7 @@ ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`
|
|
|
17260
17327
|
const tab = tabManager.getActiveTab();
|
|
17261
17328
|
if (!tab)
|
|
17262
17329
|
return asTextResponse(
|
|
17263
|
-
"No active tab. Use
|
|
17330
|
+
"No active tab. Use navigate to open a page."
|
|
17264
17331
|
);
|
|
17265
17332
|
const wc = tab.view.webContents;
|
|
17266
17333
|
let page;
|
|
@@ -17268,7 +17335,7 @@ ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`
|
|
|
17268
17335
|
page = await extractContent(wc);
|
|
17269
17336
|
} catch {
|
|
17270
17337
|
return asTextResponse(
|
|
17271
|
-
"Could not read page. Try
|
|
17338
|
+
"Could not read page. Try navigate to a working URL."
|
|
17272
17339
|
);
|
|
17273
17340
|
}
|
|
17274
17341
|
const suggestions = [];
|
|
@@ -17298,50 +17365,50 @@ ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`
|
|
|
17298
17365
|
const hasOverlays = page.overlays.some((o) => o.blocksInteraction);
|
|
17299
17366
|
if (hasOverlays) {
|
|
17300
17367
|
suggestions.push("⚠ BLOCKING OVERLAY detected — dismiss it first:");
|
|
17301
|
-
suggestions.push(" →
|
|
17302
|
-
suggestions.push(" → or
|
|
17368
|
+
suggestions.push(" → clear_overlays for stacked modals");
|
|
17369
|
+
suggestions.push(" → or dismiss_popup for a single popup");
|
|
17303
17370
|
suggestions.push("");
|
|
17304
17371
|
}
|
|
17305
17372
|
if (hasPasswordField) {
|
|
17306
17373
|
suggestions.push("🔑 LOGIN PAGE detected:");
|
|
17307
17374
|
suggestions.push(
|
|
17308
|
-
" →
|
|
17375
|
+
" → login(username, password) — handles the full flow"
|
|
17309
17376
|
);
|
|
17310
17377
|
suggestions.push(
|
|
17311
|
-
" → Or
|
|
17378
|
+
" → Or fill_form + submit_form for manual control"
|
|
17312
17379
|
);
|
|
17313
17380
|
} else if (hasSearchInput && linkCount < 10) {
|
|
17314
17381
|
suggestions.push("🔍 SEARCH PAGE detected:");
|
|
17315
17382
|
suggestions.push(
|
|
17316
|
-
" →
|
|
17383
|
+
" → search(query) — finds the box, types, submits"
|
|
17317
17384
|
);
|
|
17318
17385
|
} else if (hasSearchInput && linkCount >= 10) {
|
|
17319
17386
|
suggestions.push("📋 SEARCH RESULTS detected:");
|
|
17320
|
-
suggestions.push(" →
|
|
17387
|
+
suggestions.push(" → click on a result link");
|
|
17321
17388
|
if (hasPagination) {
|
|
17322
|
-
suggestions.push(" →
|
|
17389
|
+
suggestions.push(" → paginate('next') for more results");
|
|
17323
17390
|
}
|
|
17324
17391
|
} else if (formCount > 0) {
|
|
17325
17392
|
suggestions.push(`📝 FORM detected (${totalFields} fields):`);
|
|
17326
17393
|
suggestions.push(
|
|
17327
|
-
" →
|
|
17394
|
+
" → fill_form(fields) — fill all fields at once"
|
|
17328
17395
|
);
|
|
17329
|
-
suggestions.push(" → Or
|
|
17396
|
+
suggestions.push(" → Or type for individual fields");
|
|
17330
17397
|
} else if (hasPagination) {
|
|
17331
17398
|
suggestions.push("📄 PAGINATED CONTENT:");
|
|
17332
|
-
suggestions.push(" →
|
|
17333
|
-
suggestions.push(" →
|
|
17399
|
+
suggestions.push(" → extract_content to read this page");
|
|
17400
|
+
suggestions.push(" → paginate('next') for the next page");
|
|
17334
17401
|
} else if (page.content.length > 3e3 && page.interactiveElements.length < 10) {
|
|
17335
17402
|
suggestions.push("📖 ARTICLE/CONTENT page:");
|
|
17336
|
-
suggestions.push(" →
|
|
17337
|
-
suggestions.push(" →
|
|
17403
|
+
suggestions.push(" → extract_content for readable text");
|
|
17404
|
+
suggestions.push(" → scroll to see more");
|
|
17338
17405
|
} else {
|
|
17339
17406
|
suggestions.push("🌐 GENERAL PAGE:");
|
|
17340
17407
|
suggestions.push(
|
|
17341
|
-
" →
|
|
17408
|
+
" → extract_content to understand the page structure"
|
|
17342
17409
|
);
|
|
17343
|
-
suggestions.push(" →
|
|
17344
|
-
suggestions.push(" →
|
|
17410
|
+
suggestions.push(" → click on any element by index");
|
|
17411
|
+
suggestions.push(" → navigate to go somewhere new");
|
|
17345
17412
|
}
|
|
17346
17413
|
suggestions.push("");
|
|
17347
17414
|
suggestions.push(
|
|
@@ -17351,7 +17418,7 @@ ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`
|
|
|
17351
17418
|
}
|
|
17352
17419
|
);
|
|
17353
17420
|
server.registerTool(
|
|
17354
|
-
"
|
|
17421
|
+
"fill_form",
|
|
17355
17422
|
{
|
|
17356
17423
|
title: "Fill Form",
|
|
17357
17424
|
description: "Fill multiple form fields at once. Provide a map of field identifiers to values. Fields are matched by index, name, label, or placeholder. Much faster than calling type for each field individually.",
|
|
@@ -17402,7 +17469,7 @@ ${results.join("\n")}`;
|
|
|
17402
17469
|
}
|
|
17403
17470
|
);
|
|
17404
17471
|
server.registerTool(
|
|
17405
|
-
"
|
|
17472
|
+
"login",
|
|
17406
17473
|
{
|
|
17407
17474
|
title: "Login",
|
|
17408
17475
|
description: "Compound action: navigate to a login page, fill credentials, and submit. Handles the full login flow in one call.",
|
|
@@ -17493,7 +17560,7 @@ ${steps.join("\n")}`;
|
|
|
17493
17560
|
}
|
|
17494
17561
|
);
|
|
17495
17562
|
server.registerTool(
|
|
17496
|
-
"
|
|
17563
|
+
"search",
|
|
17497
17564
|
{
|
|
17498
17565
|
title: "Search",
|
|
17499
17566
|
description: "Compound action: find a search box on the current page, type a query, and submit. Returns the resulting page state.",
|
|
@@ -17576,7 +17643,7 @@ ${steps.join("\n")}`;
|
|
|
17576
17643
|
}
|
|
17577
17644
|
);
|
|
17578
17645
|
server.registerTool(
|
|
17579
|
-
"
|
|
17646
|
+
"paginate",
|
|
17580
17647
|
{
|
|
17581
17648
|
title: "Paginate",
|
|
17582
17649
|
description: "Navigate to the next or previous page of results. Auto-detects pagination controls.",
|
|
@@ -17632,7 +17699,7 @@ ${steps.join("\n")}`;
|
|
|
17632
17699
|
}
|
|
17633
17700
|
);
|
|
17634
17701
|
server.registerTool(
|
|
17635
|
-
"
|
|
17702
|
+
"accept_cookies",
|
|
17636
17703
|
{
|
|
17637
17704
|
title: "Accept Cookies",
|
|
17638
17705
|
description: "Dismiss cookie consent banners (OneTrust, CookieBot, GDPR popups, etc.).",
|
|
@@ -17644,7 +17711,7 @@ ${steps.join("\n")}`;
|
|
|
17644
17711
|
return withAction(
|
|
17645
17712
|
runtime2,
|
|
17646
17713
|
tabManager,
|
|
17647
|
-
"
|
|
17714
|
+
"accept_cookies",
|
|
17648
17715
|
{},
|
|
17649
17716
|
async () => {
|
|
17650
17717
|
const wc = tab.view.webContents;
|
|
@@ -17681,13 +17748,13 @@ ${steps.join("\n")}`;
|
|
|
17681
17748
|
return null;
|
|
17682
17749
|
})()
|
|
17683
17750
|
`);
|
|
17684
|
-
return dismissed || "No cookie consent banner detected. Try
|
|
17751
|
+
return dismissed || "No cookie consent banner detected. Try dismiss_popup for other overlays.";
|
|
17685
17752
|
}
|
|
17686
17753
|
);
|
|
17687
17754
|
}
|
|
17688
17755
|
);
|
|
17689
17756
|
server.registerTool(
|
|
17690
|
-
"
|
|
17757
|
+
"extract_table",
|
|
17691
17758
|
{
|
|
17692
17759
|
title: "Extract Table",
|
|
17693
17760
|
description: "Extract a table from the page as structured JSON rows with headers.",
|
|
@@ -17702,7 +17769,7 @@ ${steps.join("\n")}`;
|
|
|
17702
17769
|
return withAction(
|
|
17703
17770
|
runtime2,
|
|
17704
17771
|
tabManager,
|
|
17705
|
-
"
|
|
17772
|
+
"extract_table",
|
|
17706
17773
|
{ index, selector: rawSelector },
|
|
17707
17774
|
async () => {
|
|
17708
17775
|
const wc = tab.view.webContents;
|
|
@@ -17741,7 +17808,7 @@ ${JSON.stringify(tableJson, null, 2)}`;
|
|
|
17741
17808
|
}
|
|
17742
17809
|
);
|
|
17743
17810
|
server.registerTool(
|
|
17744
|
-
"
|
|
17811
|
+
"scroll_to_element",
|
|
17745
17812
|
{
|
|
17746
17813
|
title: "Scroll To Element",
|
|
17747
17814
|
description: "Scroll a specific element into view by index or selector.",
|
|
@@ -17757,7 +17824,7 @@ ${JSON.stringify(tableJson, null, 2)}`;
|
|
|
17757
17824
|
return withAction(
|
|
17758
17825
|
runtime2,
|
|
17759
17826
|
tabManager,
|
|
17760
|
-
"
|
|
17827
|
+
"scroll_to_element",
|
|
17761
17828
|
{ index, selector: rawSelector, position },
|
|
17762
17829
|
async () => {
|
|
17763
17830
|
const wc = tab.view.webContents;
|
|
@@ -17801,7 +17868,7 @@ ${JSON.stringify(tableJson, null, 2)}`;
|
|
|
17801
17868
|
}
|
|
17802
17869
|
);
|
|
17803
17870
|
server.registerTool(
|
|
17804
|
-
"
|
|
17871
|
+
"wait_for_navigation",
|
|
17805
17872
|
{
|
|
17806
17873
|
title: "Wait For Navigation",
|
|
17807
17874
|
description: "Wait for the current page to finish loading after a click or form submission.",
|
|
@@ -17815,7 +17882,7 @@ ${JSON.stringify(tableJson, null, 2)}`;
|
|
|
17815
17882
|
return withAction(
|
|
17816
17883
|
runtime2,
|
|
17817
17884
|
tabManager,
|
|
17818
|
-
"
|
|
17885
|
+
"wait_for_navigation",
|
|
17819
17886
|
{ timeoutMs },
|
|
17820
17887
|
async () => {
|
|
17821
17888
|
const wc = tab.view.webContents;
|
|
@@ -17857,7 +17924,7 @@ ${JSON.stringify(tableJson, null, 2)}`;
|
|
|
17857
17924
|
}
|
|
17858
17925
|
);
|
|
17859
17926
|
server.registerTool(
|
|
17860
|
-
"
|
|
17927
|
+
"vault_status",
|
|
17861
17928
|
{
|
|
17862
17929
|
title: "Check Vault Credentials",
|
|
17863
17930
|
description: "Check whether stored credentials exist for a domain. Returns credential labels and usernames but NEVER password values. Use this before vault_login to verify credentials are available.",
|
|
@@ -17899,12 +17966,12 @@ ${JSON.stringify(tableJson, null, 2)}`;
|
|
|
17899
17966
|
`Found ${matches.length} credential(s) for ${targetDomain}:
|
|
17900
17967
|
${summary}
|
|
17901
17968
|
|
|
17902
|
-
Use
|
|
17969
|
+
Use vault_login to fill the login form. Credentials are filled directly — you will NOT see the password values.`
|
|
17903
17970
|
);
|
|
17904
17971
|
}
|
|
17905
17972
|
);
|
|
17906
17973
|
server.registerTool(
|
|
17907
|
-
"
|
|
17974
|
+
"vault_login",
|
|
17908
17975
|
{
|
|
17909
17976
|
title: "Fill Login with Vault Credentials",
|
|
17910
17977
|
description: "Fill a login form on the current page using stored credentials from the Agent Credential Vault. The credential values are filled directly into the page — they are NEVER returned in this response. The user will see a consent dialog before credentials are used.",
|
|
@@ -18010,7 +18077,7 @@ Use vessel_vault_login to fill the login form. Credentials are filled directly
|
|
|
18010
18077
|
}
|
|
18011
18078
|
);
|
|
18012
18079
|
server.registerTool(
|
|
18013
|
-
"
|
|
18080
|
+
"vault_totp",
|
|
18014
18081
|
{
|
|
18015
18082
|
title: "Fill TOTP Code from Vault",
|
|
18016
18083
|
description: "Generate a TOTP 2FA code from a stored secret and fill it into a code input field. The TOTP secret and generated code are NEVER returned — only filled directly into the page.",
|
|
@@ -18095,7 +18162,7 @@ Use vessel_vault_login to fill the login form. Credentials are filled directly
|
|
|
18095
18162
|
}
|
|
18096
18163
|
);
|
|
18097
18164
|
server.registerTool(
|
|
18098
|
-
"
|
|
18165
|
+
"metrics",
|
|
18099
18166
|
{
|
|
18100
18167
|
title: "Session Metrics",
|
|
18101
18168
|
description: "Show performance metrics: total tool calls, average duration, per-tool breakdown.",
|
|
@@ -18279,7 +18346,7 @@ function startMcpServer(tabManager, runtime2, port) {
|
|
|
18279
18346
|
status: "starting",
|
|
18280
18347
|
message: `Starting MCP server on port ${port}.`
|
|
18281
18348
|
});
|
|
18282
|
-
mcpAuthToken =
|
|
18349
|
+
mcpAuthToken = getPersistentMcpAuthToken();
|
|
18283
18350
|
return new Promise((resolve) => {
|
|
18284
18351
|
const server = http.createServer(async (req, res) => {
|
|
18285
18352
|
const url = new URL(req.url || "/", `http://localhost:${port}`);
|
|
@@ -18306,7 +18373,11 @@ function startMcpServer(tabManager, runtime2, port) {
|
|
|
18306
18373
|
return;
|
|
18307
18374
|
}
|
|
18308
18375
|
const authHeader = req.headers.authorization;
|
|
18309
|
-
|
|
18376
|
+
const expected = `Bearer ${mcpAuthToken}`;
|
|
18377
|
+
const headerBuf = Buffer.from(authHeader ?? "");
|
|
18378
|
+
const expectedBuf = Buffer.from(expected);
|
|
18379
|
+
const tokenValid = headerBuf.length === expectedBuf.length && crypto$2.timingSafeEqual(headerBuf, expectedBuf);
|
|
18380
|
+
if (!authHeader || !tokenValid) {
|
|
18310
18381
|
res.writeHead(401, { "Content-Type": "application/json" });
|
|
18311
18382
|
res.end(JSON.stringify({ error: "Unauthorized — missing or invalid bearer token" }));
|
|
18312
18383
|
return;
|
|
@@ -18339,6 +18410,7 @@ function startMcpServer(tabManager, runtime2, port) {
|
|
|
18339
18410
|
server.once("error", (error) => {
|
|
18340
18411
|
const message = error.code === "EADDRINUSE" ? `Port ${port} is already in use. MCP server not started.` : error.message;
|
|
18341
18412
|
console.error("[Vessel MCP] Server error:", error);
|
|
18413
|
+
clearMcpAuthFile();
|
|
18342
18414
|
setMcpHealth({
|
|
18343
18415
|
configuredPort: port,
|
|
18344
18416
|
activePort: null,
|
|
@@ -18371,6 +18443,9 @@ function startMcpServer(tabManager, runtime2, port) {
|
|
|
18371
18443
|
message: `MCP server listening on ${endpoint}.`
|
|
18372
18444
|
});
|
|
18373
18445
|
console.log(`[Vessel MCP] Server listening on ${endpoint} (auth enabled)`);
|
|
18446
|
+
if (mcpAuthToken) {
|
|
18447
|
+
writeMcpAuthFile(endpoint, mcpAuthToken);
|
|
18448
|
+
}
|
|
18374
18449
|
finish({
|
|
18375
18450
|
ok: true,
|
|
18376
18451
|
configuredPort: port,
|
|
@@ -18396,6 +18471,7 @@ function stopMcpServer() {
|
|
|
18396
18471
|
const server = httpServer;
|
|
18397
18472
|
httpServer = null;
|
|
18398
18473
|
mcpAuthToken = null;
|
|
18474
|
+
clearMcpAuthFile();
|
|
18399
18475
|
server.close(() => {
|
|
18400
18476
|
setMcpHealth({
|
|
18401
18477
|
activePort: null,
|
|
@@ -18787,11 +18863,77 @@ function assertNumber(value, name) {
|
|
|
18787
18863
|
const VALID_APPROVAL_MODES = /* @__PURE__ */ new Set(["auto", "confirm-dangerous", "manual"]);
|
|
18788
18864
|
function registerIpcHandlers(windowState, runtime2) {
|
|
18789
18865
|
const { tabManager, chromeView, sidebarView, devtoolsPanelView, mainWindow } = windowState;
|
|
18866
|
+
const premiumApiOrigin = process.env.VESSEL_PREMIUM_API ? new URL(process.env.VESSEL_PREMIUM_API).origin : "https://vesselpremium.quantaintellect.com";
|
|
18790
18867
|
const sendToRendererViews = (channel, ...args) => {
|
|
18791
18868
|
chromeView.webContents.send(channel, ...args);
|
|
18792
18869
|
sidebarView.webContents.send(channel, ...args);
|
|
18793
18870
|
devtoolsPanelView.webContents.send(channel, ...args);
|
|
18794
18871
|
};
|
|
18872
|
+
const watchPremiumCheckoutTab = (tabId) => {
|
|
18873
|
+
const tab = tabManager.getTab(tabId);
|
|
18874
|
+
const wc = tab?.view.webContents;
|
|
18875
|
+
if (!wc) return;
|
|
18876
|
+
let completed = false;
|
|
18877
|
+
const cleanup = () => {
|
|
18878
|
+
wc.removeListener("did-navigate", onNavigate);
|
|
18879
|
+
wc.removeListener("did-navigate-in-page", onNavigateInPage);
|
|
18880
|
+
wc.removeListener("destroyed", cleanup);
|
|
18881
|
+
};
|
|
18882
|
+
const handleUrl = async (rawUrl) => {
|
|
18883
|
+
if (completed) return;
|
|
18884
|
+
let parsed;
|
|
18885
|
+
try {
|
|
18886
|
+
parsed = new URL(rawUrl);
|
|
18887
|
+
} catch {
|
|
18888
|
+
return;
|
|
18889
|
+
}
|
|
18890
|
+
if (parsed.origin !== premiumApiOrigin) return;
|
|
18891
|
+
if (parsed.pathname === "/canceled") {
|
|
18892
|
+
completed = true;
|
|
18893
|
+
trackPremiumFunnel("checkout_canceled");
|
|
18894
|
+
cleanup();
|
|
18895
|
+
return;
|
|
18896
|
+
}
|
|
18897
|
+
if (parsed.pathname !== "/success") return;
|
|
18898
|
+
completed = true;
|
|
18899
|
+
trackPremiumFunnel("checkout_success_seen");
|
|
18900
|
+
const sessionId = parsed.searchParams.get("session_id")?.trim();
|
|
18901
|
+
if (!sessionId) {
|
|
18902
|
+
trackPremiumFunnel("auto_activation_failed", {
|
|
18903
|
+
reason: "missing_session_id"
|
|
18904
|
+
});
|
|
18905
|
+
cleanup();
|
|
18906
|
+
return;
|
|
18907
|
+
}
|
|
18908
|
+
trackPremiumFunnel("auto_activation_attempted");
|
|
18909
|
+
const state2 = await verifySubscription(sessionId);
|
|
18910
|
+
if (isPremiumActiveState(state2)) {
|
|
18911
|
+
sendToRendererViews(Channels.PREMIUM_UPDATE, state2);
|
|
18912
|
+
trackPremiumFunnel("auto_activation_succeeded", {
|
|
18913
|
+
status: state2.status
|
|
18914
|
+
});
|
|
18915
|
+
} else {
|
|
18916
|
+
trackPremiumFunnel("auto_activation_failed", {
|
|
18917
|
+
status: state2.status
|
|
18918
|
+
});
|
|
18919
|
+
}
|
|
18920
|
+
cleanup();
|
|
18921
|
+
};
|
|
18922
|
+
const onNavigate = (_event, url) => {
|
|
18923
|
+
void handleUrl(url);
|
|
18924
|
+
};
|
|
18925
|
+
const onNavigateInPage = (_event, url, isMainFrame) => {
|
|
18926
|
+
if (!isMainFrame) return;
|
|
18927
|
+
void handleUrl(url);
|
|
18928
|
+
};
|
|
18929
|
+
wc.on("did-navigate", onNavigate);
|
|
18930
|
+
wc.on("did-navigate-in-page", onNavigateInPage);
|
|
18931
|
+
wc.on("destroyed", cleanup);
|
|
18932
|
+
const currentUrl = wc.getURL();
|
|
18933
|
+
if (currentUrl) {
|
|
18934
|
+
void handleUrl(currentUrl);
|
|
18935
|
+
}
|
|
18936
|
+
};
|
|
18795
18937
|
const getActiveHighlightCountSafe = async () => {
|
|
18796
18938
|
const tab = tabManager.getActiveTab();
|
|
18797
18939
|
if (!tab) return 0;
|
|
@@ -19211,7 +19353,8 @@ function registerIpcHandlers(windowState, runtime2) {
|
|
|
19211
19353
|
trackPremiumFunnel("checkout_clicked");
|
|
19212
19354
|
const result = await getCheckoutUrl(email);
|
|
19213
19355
|
if (result.ok && result.url) {
|
|
19214
|
-
tabManager.createTab(result.url);
|
|
19356
|
+
const tabId = tabManager.createTab(result.url);
|
|
19357
|
+
watchPremiumCheckoutTab(tabId);
|
|
19215
19358
|
}
|
|
19216
19359
|
return result;
|
|
19217
19360
|
});
|
|
@@ -19221,6 +19364,12 @@ function registerIpcHandlers(windowState, runtime2) {
|
|
|
19221
19364
|
sendToRendererViews(Channels.PREMIUM_UPDATE, state2);
|
|
19222
19365
|
return state2;
|
|
19223
19366
|
});
|
|
19367
|
+
electron.ipcMain.handle(Channels.PREMIUM_TRACK_CONTEXT, (_, step) => {
|
|
19368
|
+
assertString(step, "step");
|
|
19369
|
+
if (step === "chat_banner_viewed" || step === "chat_banner_clicked" || step === "settings_banner_viewed" || step === "settings_banner_clicked" || step === "welcome_banner_clicked" || step === "premium_gate_seen" || step === "premium_gate_clicked" || step === "iteration_limit_seen" || step === "iteration_limit_clicked") {
|
|
19370
|
+
trackPremiumFunnel(step);
|
|
19371
|
+
}
|
|
19372
|
+
});
|
|
19224
19373
|
electron.ipcMain.handle(Channels.PREMIUM_PORTAL, async () => {
|
|
19225
19374
|
trackPremiumFunnel("portal_opened");
|
|
19226
19375
|
const result = await getPortalUrl();
|