@quanta-intellect/vessel-browser 0.1.19 → 0.1.20
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 +119 -65
- package/out/preload/index.js +1 -1
- package/package.json +1 -1
package/out/main/index.js
CHANGED
|
@@ -362,7 +362,7 @@ class Tab {
|
|
|
362
362
|
get state() {
|
|
363
363
|
return { ...this._state };
|
|
364
364
|
}
|
|
365
|
-
navigate(url) {
|
|
365
|
+
navigate(url, postBody) {
|
|
366
366
|
if (!/^https?:\/\//i.test(url) && !url.startsWith("about:")) {
|
|
367
367
|
if (url.includes(".") && !url.includes(" ")) {
|
|
368
368
|
url = "https://" + url;
|
|
@@ -375,7 +375,24 @@ class Tab {
|
|
|
375
375
|
}
|
|
376
376
|
const policyError = checkDomainPolicy(url);
|
|
377
377
|
if (policyError) return policyError;
|
|
378
|
-
|
|
378
|
+
if (postBody) {
|
|
379
|
+
const params = new URLSearchParams();
|
|
380
|
+
for (const [key, value] of Object.entries(postBody)) {
|
|
381
|
+
params.set(key, value);
|
|
382
|
+
}
|
|
383
|
+
this.view.webContents.loadURL(url, {
|
|
384
|
+
method: "POST",
|
|
385
|
+
extraHeaders: "Content-Type: application/x-www-form-urlencoded\r\n",
|
|
386
|
+
postData: [
|
|
387
|
+
{
|
|
388
|
+
type: "rawData",
|
|
389
|
+
bytes: Buffer.from(params.toString())
|
|
390
|
+
}
|
|
391
|
+
]
|
|
392
|
+
});
|
|
393
|
+
} else {
|
|
394
|
+
this.view.webContents.loadURL(url);
|
|
395
|
+
}
|
|
379
396
|
return null;
|
|
380
397
|
}
|
|
381
398
|
goBack() {
|
|
@@ -2037,9 +2054,10 @@ class TabManager {
|
|
|
2037
2054
|
this.broadcastState();
|
|
2038
2055
|
}
|
|
2039
2056
|
}
|
|
2040
|
-
navigateTab(id, url) {
|
|
2057
|
+
navigateTab(id, url, postBody) {
|
|
2041
2058
|
const tab = this.tabs.get(id);
|
|
2042
|
-
if (tab) tab
|
|
2059
|
+
if (!tab) return `No tab with id ${id}`;
|
|
2060
|
+
return tab.navigate(url, postBody);
|
|
2043
2061
|
}
|
|
2044
2062
|
goBack(id) {
|
|
2045
2063
|
return this.tabs.get(id)?.goBack() ?? false;
|
|
@@ -7137,9 +7155,12 @@ const TOOL_DEFINITIONS = [
|
|
|
7137
7155
|
{
|
|
7138
7156
|
name: "navigate",
|
|
7139
7157
|
title: "Navigate",
|
|
7140
|
-
description: "Navigate the browser to a URL.",
|
|
7158
|
+
description: "Navigate the browser to a URL. Use postBody to submit data via POST request (e.g. form submissions).",
|
|
7141
7159
|
inputSchema: {
|
|
7142
|
-
url: zod.z.string().describe("The URL to navigate to")
|
|
7160
|
+
url: zod.z.string().describe("The URL to navigate to"),
|
|
7161
|
+
postBody: zod.z.record(zod.z.string(), zod.z.string()).optional().describe(
|
|
7162
|
+
"Optional form fields to submit via POST (application/x-www-form-urlencoded). Only supported on http/https URLs."
|
|
7163
|
+
)
|
|
7143
7164
|
},
|
|
7144
7165
|
tier: 0
|
|
7145
7166
|
},
|
|
@@ -11418,7 +11439,7 @@ async function executeAction(name, args, ctx) {
|
|
|
11418
11439
|
const createdId = ctx.tabManager.createTab(
|
|
11419
11440
|
typeof args.url === "string" && args.url.trim() ? args.url.trim() : "about:blank"
|
|
11420
11441
|
);
|
|
11421
|
-
const created = ctx.tabManager.
|
|
11442
|
+
const created = ctx.tabManager.getTab(createdId);
|
|
11422
11443
|
if (created) {
|
|
11423
11444
|
await waitForLoad$1(created.view.webContents);
|
|
11424
11445
|
return `Created tab ${createdId}${await getPostNavSummary(created.view.webContents)}`;
|
|
@@ -11431,7 +11452,8 @@ async function executeAction(name, args, ctx) {
|
|
|
11431
11452
|
if (navValidation.status === "dead") {
|
|
11432
11453
|
return `Navigation blocked: ${args.url} returned ${navValidation.detail || "dead link"}. Try a different URL or go back and choose another link.`;
|
|
11433
11454
|
}
|
|
11434
|
-
ctx.tabManager.navigateTab(tabId, args.url);
|
|
11455
|
+
const navError = ctx.tabManager.navigateTab(tabId, args.url, args.postBody);
|
|
11456
|
+
if (navError) return navError;
|
|
11435
11457
|
await waitForLoad$1(wc);
|
|
11436
11458
|
return `Navigated to ${wc.getURL()}${await getPostNavSummary(wc)}`;
|
|
11437
11459
|
}
|
|
@@ -15175,10 +15197,15 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15175
15197
|
"vessel_navigate",
|
|
15176
15198
|
{
|
|
15177
15199
|
title: "Navigate",
|
|
15178
|
-
description: "Navigate the active browser tab to a URL.",
|
|
15179
|
-
inputSchema: {
|
|
15200
|
+
description: "Navigate the active browser tab to a URL. Use postBody to submit data via POST request (e.g. form submissions).",
|
|
15201
|
+
inputSchema: {
|
|
15202
|
+
url: zod.z.string().describe("The URL to navigate to"),
|
|
15203
|
+
postBody: zod.z.record(zod.z.string(), zod.z.string()).optional().describe(
|
|
15204
|
+
"Optional form fields to submit via POST (application/x-www-form-urlencoded). Only supported on http/https URLs."
|
|
15205
|
+
)
|
|
15206
|
+
}
|
|
15180
15207
|
},
|
|
15181
|
-
async ({ url }) => {
|
|
15208
|
+
async ({ url, postBody }) => {
|
|
15182
15209
|
const tab = tabManager.getActiveTab();
|
|
15183
15210
|
if (!tab) return asTextResponse("Error: No active tab");
|
|
15184
15211
|
const preCheck = await validateLinkDestination(url);
|
|
@@ -15189,7 +15216,8 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15189
15216
|
}
|
|
15190
15217
|
return withAction(runtime2, tabManager, "navigate", { url }, async () => {
|
|
15191
15218
|
const id = tabManager.getActiveTabId();
|
|
15192
|
-
tabManager.navigateTab(id, url);
|
|
15219
|
+
const navError = tabManager.navigateTab(id, url, postBody);
|
|
15220
|
+
if (navError) return navError;
|
|
15193
15221
|
const { httpStatus } = await waitForLoadWithStatus(
|
|
15194
15222
|
tab.view.webContents
|
|
15195
15223
|
);
|
|
@@ -18235,11 +18263,14 @@ function registerIpcHandlers(windowState, runtime2) {
|
|
|
18235
18263
|
tabManager.switchTab(id);
|
|
18236
18264
|
layoutViews(windowState);
|
|
18237
18265
|
});
|
|
18238
|
-
electron.ipcMain.handle(
|
|
18239
|
-
|
|
18240
|
-
|
|
18241
|
-
|
|
18242
|
-
|
|
18266
|
+
electron.ipcMain.handle(
|
|
18267
|
+
Channels.TAB_NAVIGATE,
|
|
18268
|
+
(_, id, url, postBody) => {
|
|
18269
|
+
assertString(id, "tabId");
|
|
18270
|
+
assertString(url, "url");
|
|
18271
|
+
return tabManager.navigateTab(id, url, postBody);
|
|
18272
|
+
}
|
|
18273
|
+
);
|
|
18243
18274
|
electron.ipcMain.handle(Channels.TAB_BACK, (_, id) => {
|
|
18244
18275
|
tabManager.goBack(id);
|
|
18245
18276
|
});
|
|
@@ -19290,13 +19321,70 @@ function installDownloadHandler(chromeView) {
|
|
|
19290
19321
|
});
|
|
19291
19322
|
});
|
|
19292
19323
|
}
|
|
19293
|
-
|
|
19324
|
+
function registerHighlightShortcut(mainWindow, tabManager) {
|
|
19325
|
+
const register = () => {
|
|
19326
|
+
electron.globalShortcut.unregister("CommandOrControl+H");
|
|
19327
|
+
const success = electron.globalShortcut.register("CommandOrControl+H", () => {
|
|
19328
|
+
const activeTab = tabManager.getActiveTab();
|
|
19329
|
+
if (!activeTab) return;
|
|
19330
|
+
tabManager.captureHighlightFromActiveTab();
|
|
19331
|
+
});
|
|
19332
|
+
if (!success) {
|
|
19333
|
+
console.warn("[Vessel] Failed to register Ctrl+H shortcut");
|
|
19334
|
+
}
|
|
19335
|
+
};
|
|
19336
|
+
register();
|
|
19337
|
+
mainWindow.on("focus", register);
|
|
19338
|
+
return () => {
|
|
19339
|
+
electron.globalShortcut.unregister("CommandOrControl+H");
|
|
19340
|
+
mainWindow.removeListener("focus", register);
|
|
19341
|
+
};
|
|
19342
|
+
}
|
|
19343
|
+
function setupAppMenu() {
|
|
19344
|
+
const appMenu = electron.Menu.buildFromTemplate([
|
|
19345
|
+
{
|
|
19346
|
+
label: "Edit",
|
|
19347
|
+
submenu: [
|
|
19348
|
+
{ role: "undo" },
|
|
19349
|
+
{ role: "redo" },
|
|
19350
|
+
{ type: "separator" },
|
|
19351
|
+
{ role: "cut" },
|
|
19352
|
+
{ role: "copy" },
|
|
19353
|
+
{ role: "paste" },
|
|
19354
|
+
{ role: "selectAll" }
|
|
19355
|
+
]
|
|
19356
|
+
}
|
|
19357
|
+
]);
|
|
19358
|
+
electron.Menu.setApplicationMenu(appMenu);
|
|
19359
|
+
}
|
|
19294
19360
|
function rendererUrlFor(view) {
|
|
19295
19361
|
if (!process.env.ELECTRON_RENDERER_URL) return null;
|
|
19296
19362
|
const url = new URL(process.env.ELECTRON_RENDERER_URL);
|
|
19297
19363
|
url.searchParams.set("view", view);
|
|
19298
19364
|
return url.toString();
|
|
19299
19365
|
}
|
|
19366
|
+
function loadRenderers(chromeView, sidebarView, devtoolsPanelView) {
|
|
19367
|
+
const chromeUrl = rendererUrlFor("chrome");
|
|
19368
|
+
const sidebarUrl = rendererUrlFor("sidebar");
|
|
19369
|
+
const devtoolsUrl = rendererUrlFor("devtools");
|
|
19370
|
+
if (chromeUrl && sidebarUrl && devtoolsUrl) {
|
|
19371
|
+
chromeView.webContents.loadURL(chromeUrl);
|
|
19372
|
+
sidebarView.webContents.loadURL(sidebarUrl);
|
|
19373
|
+
devtoolsPanelView.webContents.loadURL(devtoolsUrl);
|
|
19374
|
+
} else {
|
|
19375
|
+
const rendererFile = path$1.join(__dirname, "../../renderer/index.html");
|
|
19376
|
+
chromeView.webContents.loadFile(rendererFile, {
|
|
19377
|
+
query: { view: "chrome" }
|
|
19378
|
+
});
|
|
19379
|
+
sidebarView.webContents.loadFile(rendererFile, {
|
|
19380
|
+
query: { view: "sidebar" }
|
|
19381
|
+
});
|
|
19382
|
+
devtoolsPanelView.webContents.loadFile(rendererFile, {
|
|
19383
|
+
query: { view: "devtools" }
|
|
19384
|
+
});
|
|
19385
|
+
}
|
|
19386
|
+
}
|
|
19387
|
+
let runtime = null;
|
|
19300
19388
|
function checkWritableUserData(userDataPath) {
|
|
19301
19389
|
const issues = [];
|
|
19302
19390
|
try {
|
|
@@ -19389,34 +19477,8 @@ async function bootstrap() {
|
|
|
19389
19477
|
}
|
|
19390
19478
|
});
|
|
19391
19479
|
registerIpcHandlers(windowState, runtime);
|
|
19392
|
-
|
|
19393
|
-
|
|
19394
|
-
const success = electron.globalShortcut.register("CommandOrControl+H", () => {
|
|
19395
|
-
const activeTab = tabManager.getActiveTab();
|
|
19396
|
-
if (!activeTab) return;
|
|
19397
|
-
tabManager.captureHighlightFromActiveTab();
|
|
19398
|
-
});
|
|
19399
|
-
if (!success) {
|
|
19400
|
-
console.warn("[Vessel] Failed to register Ctrl+H shortcut");
|
|
19401
|
-
}
|
|
19402
|
-
};
|
|
19403
|
-
registerHighlightShortcut();
|
|
19404
|
-
windowState.mainWindow.on("focus", registerHighlightShortcut);
|
|
19405
|
-
const appMenu = electron.Menu.buildFromTemplate([
|
|
19406
|
-
{
|
|
19407
|
-
label: "Edit",
|
|
19408
|
-
submenu: [
|
|
19409
|
-
{ role: "undo" },
|
|
19410
|
-
{ role: "redo" },
|
|
19411
|
-
{ type: "separator" },
|
|
19412
|
-
{ role: "cut" },
|
|
19413
|
-
{ role: "copy" },
|
|
19414
|
-
{ role: "paste" },
|
|
19415
|
-
{ role: "selectAll" }
|
|
19416
|
-
]
|
|
19417
|
-
}
|
|
19418
|
-
]);
|
|
19419
|
-
electron.Menu.setApplicationMenu(appMenu);
|
|
19480
|
+
registerHighlightShortcut(windowState.mainWindow, tabManager);
|
|
19481
|
+
setupAppMenu();
|
|
19420
19482
|
subscribe((state2) => {
|
|
19421
19483
|
chromeView.webContents.send(Channels.BOOKMARKS_UPDATE, state2);
|
|
19422
19484
|
sidebarView.webContents.send(Channels.BOOKMARKS_UPDATE, state2);
|
|
@@ -19428,25 +19490,7 @@ async function bootstrap() {
|
|
|
19428
19490
|
installDownloadHandler(chromeView);
|
|
19429
19491
|
startBackgroundRevalidation();
|
|
19430
19492
|
startTelemetry();
|
|
19431
|
-
|
|
19432
|
-
const sidebarUrl = rendererUrlFor("sidebar");
|
|
19433
|
-
const devtoolsUrl = rendererUrlFor("devtools");
|
|
19434
|
-
if (chromeUrl && sidebarUrl && devtoolsUrl) {
|
|
19435
|
-
chromeView.webContents.loadURL(chromeUrl);
|
|
19436
|
-
sidebarView.webContents.loadURL(sidebarUrl);
|
|
19437
|
-
devtoolsPanelView.webContents.loadURL(devtoolsUrl);
|
|
19438
|
-
} else {
|
|
19439
|
-
const rendererFile = path.join(__dirname, "../renderer/index.html");
|
|
19440
|
-
chromeView.webContents.loadFile(rendererFile, {
|
|
19441
|
-
query: { view: "chrome" }
|
|
19442
|
-
});
|
|
19443
|
-
sidebarView.webContents.loadFile(rendererFile, {
|
|
19444
|
-
query: { view: "sidebar" }
|
|
19445
|
-
});
|
|
19446
|
-
devtoolsPanelView.webContents.loadFile(rendererFile, {
|
|
19447
|
-
query: { view: "devtools" }
|
|
19448
|
-
});
|
|
19449
|
-
}
|
|
19493
|
+
loadRenderers(chromeView, sidebarView, devtoolsPanelView);
|
|
19450
19494
|
await startMcpServer(tabManager, runtime, settings2.mcpPort);
|
|
19451
19495
|
chromeView.webContents.once("did-finish-load", () => {
|
|
19452
19496
|
const savedSession = runtime.getState().session;
|
|
@@ -19461,6 +19505,16 @@ async function bootstrap() {
|
|
|
19461
19505
|
void maybeShowStartupHealthDialog(windowState);
|
|
19462
19506
|
});
|
|
19463
19507
|
}
|
|
19508
|
+
process.on("uncaughtException", (error) => {
|
|
19509
|
+
console.error("[Vessel] Uncaught exception:", error.message, error.stack);
|
|
19510
|
+
electron.app.quit();
|
|
19511
|
+
});
|
|
19512
|
+
process.on("unhandledRejection", (reason) => {
|
|
19513
|
+
console.error(
|
|
19514
|
+
"[Vessel] Unhandled rejection:",
|
|
19515
|
+
reason instanceof Error ? reason.message : reason
|
|
19516
|
+
);
|
|
19517
|
+
});
|
|
19464
19518
|
electron.app.whenReady().then(bootstrap).catch((error) => {
|
|
19465
19519
|
console.error("[Vessel] Failed to bootstrap application:", error);
|
|
19466
19520
|
electron.app.quit();
|
package/out/preload/index.js
CHANGED
|
@@ -97,7 +97,7 @@ const api = {
|
|
|
97
97
|
create: (url) => electron.ipcRenderer.invoke(Channels.TAB_CREATE, url),
|
|
98
98
|
close: (id) => electron.ipcRenderer.invoke(Channels.TAB_CLOSE, id),
|
|
99
99
|
switch: (id) => electron.ipcRenderer.invoke(Channels.TAB_SWITCH, id),
|
|
100
|
-
navigate: (id, url) => electron.ipcRenderer.invoke(Channels.TAB_NAVIGATE, id, url),
|
|
100
|
+
navigate: (id, url, postBody) => electron.ipcRenderer.invoke(Channels.TAB_NAVIGATE, id, url, postBody),
|
|
101
101
|
back: (id) => electron.ipcRenderer.invoke(Channels.TAB_BACK, id),
|
|
102
102
|
forward: (id) => electron.ipcRenderer.invoke(Channels.TAB_FORWARD, id),
|
|
103
103
|
reload: (id) => electron.ipcRenderer.invoke(Channels.TAB_RELOAD, id),
|
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.
|
|
4
|
+
"version": "0.1.20",
|
|
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": {
|