@quanta-intellect/vessel-browser 0.1.29 → 0.1.30
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 +31 -6
- package/out/main/index.js +2 -7
- package/out/preload/content-script.js +19 -0
- package/out/renderer/assets/{index-BnUB1gZc.js → index-DVD9XuhC.js} +137 -89
- package/out/renderer/assets/{index-Ct7z7yP_.css → index-eS3ccAls.css} +58 -22
- package/out/renderer/index.html +2 -2
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -162,8 +162,10 @@ The installer:
|
|
|
162
162
|
- creates a `vessel-browser-status` helper in `~/.local/bin`
|
|
163
163
|
- creates a desktop entry for Linux app launchers
|
|
164
164
|
- writes `~/.config/vessel/vessel-settings.json` with MCP port `3100`
|
|
165
|
+
- writes `~/.config/vessel/mcp-stdio-snippet.json`
|
|
165
166
|
- writes `~/.config/vessel/mcp-http-snippet.json`
|
|
166
|
-
-
|
|
167
|
+
- installs a `vessel-browser-mcp` helper that can run as a stdio-to-HTTP proxy (`--stdio`) or print config snippets
|
|
168
|
+
- prints the exact recommended stdio MCP snippet to paste into your harness config
|
|
167
169
|
|
|
168
170
|
The packaged AppImage path:
|
|
169
171
|
|
|
@@ -204,7 +206,7 @@ Notes:
|
|
|
204
206
|
|
|
205
207
|
- `npm run dev` still launches the stock Electron binary, so Linux may continue showing the default Electron gear icon in development
|
|
206
208
|
- packaged builds created with `npm run dist` / `npm run dist:dir` use the Vessel app icon
|
|
207
|
-
- the tracked smoke test runs typecheck, build, and the Electron navigation regression harness
|
|
209
|
+
- the tracked smoke test runs typecheck, build, the MCP stdio proxy regression check, and the Electron navigation regression harness
|
|
208
210
|
- for headless CI, run the smoke test under `xvfb-run -a npm run smoke:test`
|
|
209
211
|
|
|
210
212
|
### Setting up Vessel for Hermes Agent or OpenClaw
|
|
@@ -214,7 +216,7 @@ Vessel is designed to act as the browser runtime that your external agent harnes
|
|
|
214
216
|
1. Launch Vessel
|
|
215
217
|
2. Open Settings (`Ctrl+,`) to confirm MCP status, copy the endpoint, or change the MCP port
|
|
216
218
|
3. Optional: set an Obsidian vault path or session preferences
|
|
217
|
-
4. Start Hermes Agent or OpenClaw and
|
|
219
|
+
4. Start Hermes Agent or OpenClaw and point it at Vessel — the easiest way is `vessel-browser-mcp --stdio` as the MCP command (auth is resolved automatically), or connect directly to `http://127.0.0.1:<mcpPort>/mcp` with the bearer token from `~/.config/vessel/mcp-auth.json`
|
|
218
220
|
5. Use the Supervisor panel in Vessel's sidebar to pause the agent, change approval mode, review pending approvals, checkpoint, or restore the browser session while the harness runs
|
|
219
221
|
6. Use the Bookmarks panel to organize saved pages into folders and expose those bookmarks back to the agent over MCP
|
|
220
222
|
|
|
@@ -316,7 +318,23 @@ The extraction output can distinguish:
|
|
|
316
318
|
- active blocking overlays
|
|
317
319
|
- dormant consent/modal UI present in the DOM but not active for the current session or region
|
|
318
320
|
|
|
319
|
-
|
|
321
|
+
Stdio proxy MCP config (recommended — resolves auth automatically):
|
|
322
|
+
|
|
323
|
+
```json
|
|
324
|
+
{
|
|
325
|
+
"mcpServers": {
|
|
326
|
+
"vessel": {
|
|
327
|
+
"command": "vessel-browser-mcp",
|
|
328
|
+
"args": ["--stdio"]
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
The stdio proxy reads the bearer token from `~/.config/vessel/mcp-auth.json` at connection time, so no manual token management is needed.
|
|
335
|
+
Vessel must already be running when your MCP client connects, and `~/.config/vessel/mcp-auth.json` must exist from install or first launch.
|
|
336
|
+
|
|
337
|
+
Generic HTTP MCP config (requires copying the token manually):
|
|
320
338
|
|
|
321
339
|
```json
|
|
322
340
|
{
|
|
@@ -346,8 +364,9 @@ mcp_servers:
|
|
|
346
364
|
|
|
347
365
|
## Configuration
|
|
348
366
|
|
|
349
|
-
The installer writes
|
|
367
|
+
The installer writes three snippets to:
|
|
350
368
|
|
|
369
|
+
- `~/.config/vessel/mcp-stdio-snippet.json`
|
|
351
370
|
- `~/.config/vessel/mcp-http-snippet.json`
|
|
352
371
|
- `~/.config/vessel/mcp-hermes-snippet.yaml`
|
|
353
372
|
|
|
@@ -360,9 +379,15 @@ vessel-browser-mcp
|
|
|
360
379
|
Helper examples:
|
|
361
380
|
|
|
362
381
|
```bash
|
|
363
|
-
#
|
|
382
|
+
# Run as stdio-to-HTTP proxy (for MCP client integration)
|
|
383
|
+
vessel-browser-mcp --stdio
|
|
384
|
+
|
|
385
|
+
# Recommended stdio MCP snippet
|
|
364
386
|
vessel-browser-mcp
|
|
365
387
|
|
|
388
|
+
# Generic JSON snippet with Authorization header
|
|
389
|
+
vessel-browser-mcp --format json
|
|
390
|
+
|
|
366
391
|
# Hermes-ready YAML snippet with Authorization header
|
|
367
392
|
vessel-browser-mcp --format hermes
|
|
368
393
|
|
package/out/main/index.js
CHANGED
|
@@ -5177,9 +5177,6 @@ class AnthropicProvider {
|
|
|
5177
5177
|
let iterationsUsed = 0;
|
|
5178
5178
|
for (let i = 0; i < maxIterations; i++) {
|
|
5179
5179
|
iterationsUsed = i + 1;
|
|
5180
|
-
const msgTokenEstimate = JSON.stringify(messages).length;
|
|
5181
|
-
const sysTokenEstimate = systemPrompt.length;
|
|
5182
|
-
const streamStartTime = Date.now();
|
|
5183
5180
|
const stream = this.client.messages.stream(
|
|
5184
5181
|
{
|
|
5185
5182
|
model: this.model,
|
|
@@ -5496,8 +5493,6 @@ class OpenAICompatProvider {
|
|
|
5496
5493
|
let iterationsUsed = 0;
|
|
5497
5494
|
for (let i = 0; i < maxIterations; i++) {
|
|
5498
5495
|
iterationsUsed = i + 1;
|
|
5499
|
-
const msgTokenEstimate = JSON.stringify(messages).length;
|
|
5500
|
-
const streamStartTime = Date.now();
|
|
5501
5496
|
let textAccum = "";
|
|
5502
5497
|
const toolCallAccums = {};
|
|
5503
5498
|
let finishReason = null;
|
|
@@ -12135,7 +12130,7 @@ async function executeAction(name, args, ctx) {
|
|
|
12135
12130
|
}
|
|
12136
12131
|
case "click": {
|
|
12137
12132
|
if (!wc) return "Error: No active tab";
|
|
12138
|
-
const selector = await resolveSelector$1(wc, args.index, args.selector);
|
|
12133
|
+
const selector = typeof args.selector === "string" && args.selector.trim() ? await resolveSelector$1(wc, void 0, args.selector) : typeof args.index === "number" ? `__vessel_idx:${args.index}` : await resolveSelector$1(wc, args.index, args.selector);
|
|
12139
12134
|
if (!selector) return "Error: No element index or selector provided";
|
|
12140
12135
|
return clickResolvedSelector$1(wc, selector);
|
|
12141
12136
|
}
|
|
@@ -15966,7 +15961,7 @@ ${buildScopedContext(pageContent, mode)}`;
|
|
|
15966
15961
|
{ index, selector },
|
|
15967
15962
|
async () => {
|
|
15968
15963
|
const wc = tab.view.webContents;
|
|
15969
|
-
const resolvedSelector = await resolveSelector(wc, index, selector);
|
|
15964
|
+
const resolvedSelector = typeof selector === "string" && selector.trim() ? await resolveSelector(wc, void 0, selector) : typeof index === "number" ? `__vessel_idx:${index}` : await resolveSelector(wc, index, selector);
|
|
15970
15965
|
if (!resolvedSelector) {
|
|
15971
15966
|
return "Error: No index or selector provided";
|
|
15972
15967
|
}
|
|
@@ -3195,6 +3195,25 @@ function interactByIndex(index, action, value) {
|
|
|
3195
3195
|
if (action === "click") {
|
|
3196
3196
|
el.focus();
|
|
3197
3197
|
el.click();
|
|
3198
|
+
if (el instanceof HTMLInputElement) {
|
|
3199
|
+
if (el.type === "checkbox") {
|
|
3200
|
+
const label = getInputLabel(el) || el.getAttribute("aria-label") || el.name || "checkbox";
|
|
3201
|
+
return `${el.checked ? "Checked" : "Unchecked"}: ${label}`;
|
|
3202
|
+
}
|
|
3203
|
+
if (el.type === "radio") {
|
|
3204
|
+
const label = getTrimmedText(el.value) || getInputLabel(el) || el.getAttribute("aria-label") || el.name || "radio";
|
|
3205
|
+
return `${el.checked ? "Selected" : "Clicked"}: ${label}`;
|
|
3206
|
+
}
|
|
3207
|
+
}
|
|
3208
|
+
const role = el.getAttribute("role");
|
|
3209
|
+
if (role === "checkbox" || role === "radio") {
|
|
3210
|
+
const label = getTrimmedText(el.getAttribute("aria-label")) || getTrimmedText(el.textContent) || el.tagName.toLowerCase();
|
|
3211
|
+
const ariaChecked = el.getAttribute("aria-checked");
|
|
3212
|
+
if (role === "checkbox") {
|
|
3213
|
+
return `${ariaChecked === "true" ? "Checked" : "Unchecked"}: ${label}`;
|
|
3214
|
+
}
|
|
3215
|
+
return `${ariaChecked === "true" ? "Selected" : "Clicked"}: ${label}`;
|
|
3216
|
+
}
|
|
3198
3217
|
return "Clicked: " + (el.getAttribute("aria-label") || el.textContent?.trim().slice(0, 60) || el.tagName.toLowerCase());
|
|
3199
3218
|
}
|
|
3200
3219
|
if (action === "focus") {
|
|
@@ -1696,6 +1696,7 @@ function getAgentPresence(state, currentTime = Date.now()) {
|
|
|
1696
1696
|
return "idle";
|
|
1697
1697
|
}
|
|
1698
1698
|
var _tmpl$$d = /* @__PURE__ */ template(`<img class=tab-favicon alt>`), _tmpl$2$b = /* @__PURE__ */ template(`<span class=tab-favicon-fallback>`), _tmpl$3$8 = /* @__PURE__ */ template(`<div class=tab-bar><div class=tab-list><button class=tab-new data-tooltip="New Tab">+`), _tmpl$4$8 = /* @__PURE__ */ template(`<div role=tab><span class=tab-title></span><button class=tab-close>×`), _tmpl$5$6 = /* @__PURE__ */ template(`<span class=tab-agent-indicator aria-hidden=true title="Agent active on this tab">`), _tmpl$6$6 = /* @__PURE__ */ template(`<span class=tab-loading>`);
|
|
1699
|
+
const TAB_CLOSE_MS = 200;
|
|
1699
1700
|
function stringToHue(str) {
|
|
1700
1701
|
let hash = 0;
|
|
1701
1702
|
for (let i = 0; i < str.length; i++) {
|
|
@@ -1747,7 +1748,19 @@ const TabBar = () => {
|
|
|
1747
1748
|
runtimeState: runtimeState2
|
|
1748
1749
|
} = useRuntime();
|
|
1749
1750
|
const now2 = useNow();
|
|
1751
|
+
const [closingTabIds, setClosingTabIds] = createSignal(/* @__PURE__ */ new Set());
|
|
1750
1752
|
const modelActiveTabIds = createMemo(() => getAgentActiveTabIds(runtimeState2(), now2()));
|
|
1753
|
+
const handleClose = (id) => {
|
|
1754
|
+
setClosingTabIds((prev) => new Set(prev).add(id));
|
|
1755
|
+
setTimeout(() => {
|
|
1756
|
+
closeTab(id);
|
|
1757
|
+
setClosingTabIds((prev) => {
|
|
1758
|
+
const next = new Set(prev);
|
|
1759
|
+
next.delete(id);
|
|
1760
|
+
return next;
|
|
1761
|
+
});
|
|
1762
|
+
}, TAB_CLOSE_MS);
|
|
1763
|
+
};
|
|
1751
1764
|
return (() => {
|
|
1752
1765
|
var _el$3 = _tmpl$3$8(), _el$4 = _el$3.firstChild, _el$5 = _el$4.firstChild;
|
|
1753
1766
|
insert(_el$4, createComponent(For, {
|
|
@@ -1757,7 +1770,7 @@ const TabBar = () => {
|
|
|
1757
1770
|
children: (tab) => (() => {
|
|
1758
1771
|
var _el$6 = _tmpl$4$8(), _el$7 = _el$6.firstChild, _el$8 = _el$7.nextSibling;
|
|
1759
1772
|
_el$6.addEventListener("auxclick", (e) => {
|
|
1760
|
-
if (e.button === 1)
|
|
1773
|
+
if (e.button === 1) handleClose(tab.id);
|
|
1761
1774
|
});
|
|
1762
1775
|
_el$6.$$click = () => switchTab(tab.id);
|
|
1763
1776
|
insert(_el$6, createComponent(TabFavicon, {
|
|
@@ -1782,16 +1795,18 @@ const TabBar = () => {
|
|
|
1782
1795
|
})(), _el$8);
|
|
1783
1796
|
_el$8.$$click = (e) => {
|
|
1784
1797
|
e.stopPropagation();
|
|
1785
|
-
|
|
1798
|
+
handleClose(tab.id);
|
|
1786
1799
|
};
|
|
1787
1800
|
createRenderEffect((_p$) => {
|
|
1788
|
-
var _v$ = `tab-item ${tab.id === activeTabId2() ? "active" : ""} ${modelActiveTabIds().has(tab.id) ? "model-active" : ""}`, _v$2 = modelActiveTabIds().has(tab.id) ? `${tab.title || "New Tab"} • Agent active` : tab.title;
|
|
1801
|
+
var _v$ = `tab-item ${tab.id === activeTabId2() ? "active" : ""} ${modelActiveTabIds().has(tab.id) ? "model-active" : ""}`, _v$2 = !!closingTabIds().has(tab.id), _v$3 = modelActiveTabIds().has(tab.id) ? `${tab.title || "New Tab"} • Agent active` : tab.title;
|
|
1789
1802
|
_v$ !== _p$.e && className(_el$6, _p$.e = _v$);
|
|
1790
|
-
_v$2 !== _p$.t &&
|
|
1803
|
+
_v$2 !== _p$.t && _el$6.classList.toggle("closing", _p$.t = _v$2);
|
|
1804
|
+
_v$3 !== _p$.a && setAttribute(_el$6, "title", _p$.a = _v$3);
|
|
1791
1805
|
return _p$;
|
|
1792
1806
|
}, {
|
|
1793
1807
|
e: void 0,
|
|
1794
|
-
t: void 0
|
|
1808
|
+
t: void 0,
|
|
1809
|
+
a: void 0
|
|
1795
1810
|
});
|
|
1796
1811
|
return _el$6;
|
|
1797
1812
|
})()
|
|
@@ -2122,6 +2137,15 @@ function useScrollFade(el) {
|
|
|
2122
2137
|
observer.disconnect();
|
|
2123
2138
|
});
|
|
2124
2139
|
}
|
|
2140
|
+
function formatTime(iso, options) {
|
|
2141
|
+
const d = new Date(iso);
|
|
2142
|
+
if (Number.isNaN(d.getTime())) return "";
|
|
2143
|
+
return d.toLocaleTimeString([], {
|
|
2144
|
+
hour: options?.includeSeconds ? "2-digit" : "numeric",
|
|
2145
|
+
minute: "2-digit",
|
|
2146
|
+
...options?.includeSeconds && { second: "2-digit" }
|
|
2147
|
+
});
|
|
2148
|
+
}
|
|
2125
2149
|
var _tmpl$$9 = /* @__PURE__ */ template(`<span class=agent-transcript-live><span class=agent-transcript-live-dot aria-hidden=true></span>Live`), _tmpl$2$8 = /* @__PURE__ */ template(`<div class=agent-transcript-list>`), _tmpl$3$7 = /* @__PURE__ */ template(`<aside class=agent-transcript-dock><div class=agent-transcript-header><div class=agent-transcript-title-row><span class=agent-transcript-title>Agent Transcript</span></div><div class=agent-transcript-actions><button class=agent-transcript-icon></button><button class=agent-transcript-icon data-tooltip=Hide>×`), _tmpl$4$7 = /* @__PURE__ */ template(`<article><div class=agent-transcript-meta><span class=agent-transcript-badge></span><span class=agent-transcript-time></span></div><div class=agent-transcript-text>`);
|
|
2126
2150
|
const AgentTranscriptDock = () => {
|
|
2127
2151
|
const {
|
|
@@ -2140,14 +2164,6 @@ const AgentTranscriptDock = () => {
|
|
|
2140
2164
|
});
|
|
2141
2165
|
const visibleEntries = createMemo(() => runtimeState2().transcript.slice(-6).reverse());
|
|
2142
2166
|
const hasStreamingEntry = createMemo(() => visibleEntries().some((entry) => entry.status === "streaming"));
|
|
2143
|
-
const formatTime2 = (value) => {
|
|
2144
|
-
const date = new Date(value);
|
|
2145
|
-
if (Number.isNaN(date.getTime())) return "";
|
|
2146
|
-
return date.toLocaleTimeString([], {
|
|
2147
|
-
hour: "numeric",
|
|
2148
|
-
minute: "2-digit"
|
|
2149
|
-
});
|
|
2150
|
-
};
|
|
2151
2167
|
const hideDock = async () => {
|
|
2152
2168
|
setMode("off");
|
|
2153
2169
|
await window.vessel.settings.set("agentTranscriptMode", "off");
|
|
@@ -2185,7 +2201,7 @@ const AgentTranscriptDock = () => {
|
|
|
2185
2201
|
children: (entry) => (() => {
|
|
2186
2202
|
var _el$0 = _tmpl$4$7(), _el$1 = _el$0.firstChild, _el$10 = _el$1.firstChild, _el$11 = _el$10.nextSibling, _el$12 = _el$1.nextSibling;
|
|
2187
2203
|
insert(_el$10, () => entry.title || entry.kind);
|
|
2188
|
-
insert(_el$11, () =>
|
|
2204
|
+
insert(_el$11, () => formatTime(entry.updatedAt));
|
|
2189
2205
|
insert(_el$12, () => entry.text);
|
|
2190
2206
|
createRenderEffect((_p$) => {
|
|
2191
2207
|
var _v$3 = `agent-transcript-entry ${entry.kind}`, _v$4 = !!(entry.status === "streaming");
|
|
@@ -2459,7 +2475,35 @@ function useAI() {
|
|
|
2459
2475
|
}
|
|
2460
2476
|
};
|
|
2461
2477
|
}
|
|
2478
|
+
function useAnimatedPresence(isOpen, exitDurationMs) {
|
|
2479
|
+
const [visible, setVisible] = createSignal(false);
|
|
2480
|
+
const [closing, setClosing] = createSignal(false);
|
|
2481
|
+
let exitTimer;
|
|
2482
|
+
createEffect(() => {
|
|
2483
|
+
const open = isOpen();
|
|
2484
|
+
if (open) {
|
|
2485
|
+
if (exitTimer) {
|
|
2486
|
+
clearTimeout(exitTimer);
|
|
2487
|
+
exitTimer = void 0;
|
|
2488
|
+
}
|
|
2489
|
+
setClosing(false);
|
|
2490
|
+
setVisible(true);
|
|
2491
|
+
} else if (visible()) {
|
|
2492
|
+
setClosing(true);
|
|
2493
|
+
exitTimer = window.setTimeout(() => {
|
|
2494
|
+
setVisible(false);
|
|
2495
|
+
setClosing(false);
|
|
2496
|
+
exitTimer = void 0;
|
|
2497
|
+
}, exitDurationMs);
|
|
2498
|
+
}
|
|
2499
|
+
});
|
|
2500
|
+
onCleanup(() => {
|
|
2501
|
+
if (exitTimer) clearTimeout(exitTimer);
|
|
2502
|
+
});
|
|
2503
|
+
return { visible, closing };
|
|
2504
|
+
}
|
|
2462
2505
|
var _tmpl$$8 = /* @__PURE__ */ template(`<div class=command-bar-no-provider><p>Configure a chat provider to start using the AI assistant.</p><button class=command-bar-no-provider-btn>Open Settings <kbd>Ctrl+,`), _tmpl$2$7 = /* @__PURE__ */ template(`<div class=command-bar-recent><span class=command-bar-recent-label>Recent</span><div class=command-bar-recent-list>`), _tmpl$3$6 = /* @__PURE__ */ template(`<span>Try "summarize" or ask a question`), _tmpl$4$6 = /* @__PURE__ */ template(`<div class=command-bar-overlay><div class=command-bar><form><div class=command-bar-icon><svg width=16 height=16 viewBox="0 0 16 16"><circle cx=8 cy=8 r=6 fill=none stroke=var(--accent-primary) stroke-width=1.5></circle><circle cx=6 cy=7 r=0.8 fill=var(--accent-primary)></circle><circle cx=10 cy=7 r=0.8 fill=var(--accent-primary)></circle><path d="M6 10c0.5 0.8 3.5 0.8 4 0"fill=none stroke=var(--accent-primary) stroke-width=0.8 stroke-linecap=round></path></svg></div><input class=command-bar-input type=text></form><div class=command-bar-hints><span><kbd>Enter</kbd> to ask</span><span><kbd>Esc</kbd> to close`), _tmpl$5$5 = /* @__PURE__ */ template(`<button class=command-bar-recent-item type=button>`), _tmpl$6$5 = /* @__PURE__ */ template(`<span>Set up a provider in Settings first`);
|
|
2506
|
+
const COMMAND_BAR_EXIT_MS = 200;
|
|
2463
2507
|
const CommandBar = () => {
|
|
2464
2508
|
const {
|
|
2465
2509
|
commandBarOpen: commandBarOpen2,
|
|
@@ -2467,6 +2511,10 @@ const CommandBar = () => {
|
|
|
2467
2511
|
toggleSidebar,
|
|
2468
2512
|
openSettings
|
|
2469
2513
|
} = useUI();
|
|
2514
|
+
const {
|
|
2515
|
+
visible,
|
|
2516
|
+
closing
|
|
2517
|
+
} = useAnimatedPresence(commandBarOpen2, COMMAND_BAR_EXIT_MS);
|
|
2470
2518
|
const {
|
|
2471
2519
|
query,
|
|
2472
2520
|
recentQueries: recentQueries2,
|
|
@@ -2505,7 +2553,7 @@ const CommandBar = () => {
|
|
|
2505
2553
|
};
|
|
2506
2554
|
return createComponent(Show, {
|
|
2507
2555
|
get when() {
|
|
2508
|
-
return
|
|
2556
|
+
return visible();
|
|
2509
2557
|
},
|
|
2510
2558
|
get children() {
|
|
2511
2559
|
var _el$ = _tmpl$4$6(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild, _el$4 = _el$3.firstChild, _el$5 = _el$4.nextSibling, _el$10 = _el$3.nextSibling, _el$11 = _el$10.firstChild;
|
|
@@ -2562,13 +2610,15 @@ const CommandBar = () => {
|
|
|
2562
2610
|
}
|
|
2563
2611
|
}), null);
|
|
2564
2612
|
createRenderEffect((_p$) => {
|
|
2565
|
-
var _v$ = hasProvider() ? "Ask about this page, summarize, or search..." : "No chat provider configured", _v$
|
|
2566
|
-
_v$ !== _p$.e &&
|
|
2567
|
-
_v$2 !== _p$.t && (_el$5
|
|
2613
|
+
var _v$ = !!closing(), _v$2 = hasProvider() ? "Ask about this page, summarize, or search..." : "No chat provider configured", _v$3 = !hasProvider();
|
|
2614
|
+
_v$ !== _p$.e && _el$.classList.toggle("closing", _p$.e = _v$);
|
|
2615
|
+
_v$2 !== _p$.t && setAttribute(_el$5, "placeholder", _p$.t = _v$2);
|
|
2616
|
+
_v$3 !== _p$.a && (_el$5.disabled = _p$.a = _v$3);
|
|
2568
2617
|
return _p$;
|
|
2569
2618
|
}, {
|
|
2570
2619
|
e: void 0,
|
|
2571
|
-
t: void 0
|
|
2620
|
+
t: void 0,
|
|
2621
|
+
a: void 0
|
|
2572
2622
|
});
|
|
2573
2623
|
createRenderEffect(() => _el$5.value = input());
|
|
2574
2624
|
return _el$;
|
|
@@ -4034,6 +4084,9 @@ ${token}
|
|
|
4034
4084
|
ALLOWED_ATTR: ["href", "target", "rel", "data-language", "style", "class"]
|
|
4035
4085
|
});
|
|
4036
4086
|
}
|
|
4087
|
+
function isPremiumStatus(status) {
|
|
4088
|
+
return status === "active" || status === "trialing";
|
|
4089
|
+
}
|
|
4037
4090
|
const WORD_NORMALIZATIONS = [
|
|
4038
4091
|
[/\bminutes?\b/g, "min"],
|
|
4039
4092
|
[/\bmins?\b/g, "min"],
|
|
@@ -4643,10 +4696,7 @@ const AutomationTab = (props) => {
|
|
|
4643
4696
|
const [premiumData] = createResource(() => window.vessel.premium.getState().catch(() => ({
|
|
4644
4697
|
status: "free"
|
|
4645
4698
|
})));
|
|
4646
|
-
const isPremium = () =>
|
|
4647
|
-
const s = premiumData()?.status;
|
|
4648
|
-
return s === "active" || s === "trialing";
|
|
4649
|
-
};
|
|
4699
|
+
const isPremium = () => isPremiumStatus(premiumData()?.status);
|
|
4650
4700
|
const [installedKits, {
|
|
4651
4701
|
refetch: refetchInstalled
|
|
4652
4702
|
}] = createResource(() => isPremium(), (active) => active ? window.vessel.automation.getInstalled().catch(() => []) : Promise.resolve([]));
|
|
@@ -5456,10 +5506,7 @@ const Sidebar = (props) => {
|
|
|
5456
5506
|
expiresAt: ""
|
|
5457
5507
|
});
|
|
5458
5508
|
const trackedPremiumContexts = /* @__PURE__ */ new Set();
|
|
5459
|
-
const isPremium = () =>
|
|
5460
|
-
const status = premiumState().status;
|
|
5461
|
-
return status === "active" || status === "trialing";
|
|
5462
|
-
};
|
|
5509
|
+
const isPremium = () => isPremiumStatus(premiumState().status);
|
|
5463
5510
|
const trackPremiumContext = (step) => {
|
|
5464
5511
|
if (trackedPremiumContexts.has(step)) return;
|
|
5465
5512
|
trackedPremiumContexts.add(step);
|
|
@@ -6549,18 +6596,6 @@ ${contextBlock}` : contextBlock);
|
|
|
6549
6596
|
};
|
|
6550
6597
|
delegateEvents(["click", "pointerdown", "input", "keydown"]);
|
|
6551
6598
|
var _tmpl$$3 = /* @__PURE__ */ template(`<div class=devtools-console>`), _tmpl$2$3 = /* @__PURE__ */ template(`<div class=devtools-empty>Waiting for console output... Console monitoring activates when an agent uses devtools.`), _tmpl$3$2 = /* @__PURE__ */ template(`<div><span></span><span class=console-time></span><span class=console-text></span><span class=console-source>`), _tmpl$4$2 = /* @__PURE__ */ template(`<div class=devtools-network><div class=network-header><span>Method</span><span>URL</span><span>Status</span><span>Type</span><span>Time`), _tmpl$5$2 = /* @__PURE__ */ template(`<div class=devtools-empty>Waiting for network requests... Network monitoring activates when an agent uses devtools.`), _tmpl$6$2 = /* @__PURE__ */ template(`<div><span class=network-method></span><span class=network-url></span><span></span><span class=network-type></span><span class=network-duration>`), _tmpl$7$1 = /* @__PURE__ */ template(`<div class=devtools-activity>`), _tmpl$8$1 = /* @__PURE__ */ template(`<div class=devtools-empty>Waiting for agent devtools activity...`), _tmpl$9$1 = /* @__PURE__ */ template(`<div class=activity-entry><span class=activity-time></span><span class=activity-tool></span><span class=activity-args></span><span></span><span class=activity-duration>`), _tmpl$0$1 = /* @__PURE__ */ template(`<span class="devtools-tab-badge error">`), _tmpl$1$1 = /* @__PURE__ */ template(`<span class="devtools-tab-badge count">`), _tmpl$10$1 = /* @__PURE__ */ template(`<div class=export-date-inputs><div class=export-date-row><span class=export-date-label>From</span><input class=export-date-input type=date></div><div class=export-date-row><span class=export-date-label>To</span><input class=export-date-input type=date>`), _tmpl$11$1 = /* @__PURE__ */ template(`<div class=devtools-export-dropdown><div class=export-section><div class=export-section-label>Log Types</div><label class=export-checkbox><input type=checkbox>Console</label><label class=export-checkbox><input type=checkbox>Network</label><label class=export-checkbox><input type=checkbox>Activity</label></div><div class=export-section><div class=export-section-label>Date Range</div><div class=export-date-btns><button>Today</button><button>Custom</button></div></div><button class=export-submit>Export JSON`), _tmpl$12$1 = /* @__PURE__ */ template(`<div class=devtools-panel><div class=devtools-tabs><button>Console</button><button>Network</button><button>Activity</button><div class=devtools-tab-spacer></div><div class=devtools-export-wrap><button title="Export Logs"><svg width=13 height=13 viewBox="0 0 13 13"fill=none style=vertical-align:middle><path d="M6.5 1v7M3.5 5l3 3 3-3"stroke=currentColor stroke-width=1.3 stroke-linecap=round stroke-linejoin=round></path><path d="M1 9.5v1A1.5 1.5 0 0 0 2.5 12h8A1.5 1.5 0 0 0 12 10.5v-1"stroke=currentColor stroke-width=1.3 stroke-linecap=round></path></svg></button></div><button class=devtools-close-btn title="Close DevTools">×</button></div><div class=devtools-content>`);
|
|
6552
|
-
function formatTime(iso) {
|
|
6553
|
-
try {
|
|
6554
|
-
const d = new Date(iso);
|
|
6555
|
-
return d.toLocaleTimeString([], {
|
|
6556
|
-
hour: "2-digit",
|
|
6557
|
-
minute: "2-digit",
|
|
6558
|
-
second: "2-digit"
|
|
6559
|
-
});
|
|
6560
|
-
} catch {
|
|
6561
|
-
return "";
|
|
6562
|
-
}
|
|
6563
|
-
}
|
|
6564
6599
|
function statusClass(status) {
|
|
6565
6600
|
if (status == null) return "pending";
|
|
6566
6601
|
if (status >= 200 && status < 300) return "ok";
|
|
@@ -6635,7 +6670,9 @@ const ConsoleView = (props) => {
|
|
|
6635
6670
|
children: (entry) => (() => {
|
|
6636
6671
|
var _el$3 = _tmpl$3$2(), _el$4 = _el$3.firstChild, _el$5 = _el$4.nextSibling, _el$6 = _el$5.nextSibling, _el$7 = _el$6.nextSibling;
|
|
6637
6672
|
insert(_el$4, () => entry.level);
|
|
6638
|
-
insert(_el$5, () => formatTime(entry.timestamp
|
|
6673
|
+
insert(_el$5, () => formatTime(entry.timestamp, {
|
|
6674
|
+
includeSeconds: true
|
|
6675
|
+
}));
|
|
6639
6676
|
insert(_el$6, () => entry.text);
|
|
6640
6677
|
insert(_el$7, () => shortenSource(entry.url, entry.line));
|
|
6641
6678
|
createRenderEffect((_p$) => {
|
|
@@ -6734,7 +6771,9 @@ const ActivityView = (props) => {
|
|
|
6734
6771
|
},
|
|
6735
6772
|
children: (entry) => (() => {
|
|
6736
6773
|
var _el$17 = _tmpl$9$1(), _el$18 = _el$17.firstChild, _el$19 = _el$18.nextSibling, _el$20 = _el$19.nextSibling, _el$21 = _el$20.nextSibling, _el$22 = _el$21.nextSibling;
|
|
6737
|
-
insert(_el$18, () => formatTime(entry.timestamp
|
|
6774
|
+
insert(_el$18, () => formatTime(entry.timestamp, {
|
|
6775
|
+
includeSeconds: true
|
|
6776
|
+
}));
|
|
6738
6777
|
insert(_el$19, () => entry.tool.replace("devtools_", ""));
|
|
6739
6778
|
insert(_el$20, () => entry.args);
|
|
6740
6779
|
insert(_el$21, (() => {
|
|
@@ -6994,6 +7033,9 @@ var _tmpl$$2 = /* @__PURE__ */ template(`<div class=welcome-banner-actions><butt
|
|
|
6994
7033
|
inset 0 1px 0 rgba(255, 255, 255, 0.04);
|
|
6995
7034
|
animation: command-bar-enter 350ms var(--ease-out-expo) both;
|
|
6996
7035
|
}
|
|
7036
|
+
.command-bar-overlay.closing .settings-panel {
|
|
7037
|
+
animation: command-bar-exit 200ms var(--ease-in-out) both;
|
|
7038
|
+
}
|
|
6997
7039
|
.settings-title {
|
|
6998
7040
|
font-size: 16px;
|
|
6999
7041
|
font-weight: 600;
|
|
@@ -7580,6 +7622,10 @@ const Settings = () => {
|
|
|
7580
7622
|
settingsOpen: settingsOpen2,
|
|
7581
7623
|
closeSettings
|
|
7582
7624
|
} = useUI();
|
|
7625
|
+
const {
|
|
7626
|
+
visible: settingsVisible,
|
|
7627
|
+
closing: settingsClosing
|
|
7628
|
+
} = useAnimatedPresence(settingsOpen2, 200);
|
|
7583
7629
|
const [autoRestoreSession, setAutoRestoreSession] = createSignal(true);
|
|
7584
7630
|
const [clearBookmarksOnLaunch, setClearBookmarksOnLaunch] = createSignal(false);
|
|
7585
7631
|
const [obsidianVaultPath, setObsidianVaultPath] = createSignal("");
|
|
@@ -7841,7 +7887,7 @@ const Settings = () => {
|
|
|
7841
7887
|
};
|
|
7842
7888
|
return createComponent(Show, {
|
|
7843
7889
|
get when() {
|
|
7844
|
-
return
|
|
7890
|
+
return settingsVisible();
|
|
7845
7891
|
},
|
|
7846
7892
|
get children() {
|
|
7847
7893
|
return [(() => {
|
|
@@ -7962,9 +8008,9 @@ const Settings = () => {
|
|
|
7962
8008
|
})()
|
|
7963
8009
|
}), null);
|
|
7964
8010
|
createRenderEffect((_p$) => {
|
|
7965
|
-
var _v$
|
|
7966
|
-
_v$
|
|
7967
|
-
_v$
|
|
8011
|
+
var _v$0 = !!(issue.severity === "warning"), _v$1 = !!(issue.severity === "error");
|
|
8012
|
+
_v$0 !== _p$.e && _el$110.classList.toggle("warning", _p$.e = _v$0);
|
|
8013
|
+
_v$1 !== _p$.t && _el$110.classList.toggle("error", _p$.t = _v$1);
|
|
7968
8014
|
return _p$;
|
|
7969
8015
|
}, {
|
|
7970
8016
|
e: void 0,
|
|
@@ -8148,9 +8194,9 @@ const Settings = () => {
|
|
|
8148
8194
|
var _el$124 = _tmpl$29();
|
|
8149
8195
|
insert(_el$124, () => msg().text);
|
|
8150
8196
|
createRenderEffect((_p$) => {
|
|
8151
|
-
var _v$
|
|
8152
|
-
_v$
|
|
8153
|
-
_v$
|
|
8197
|
+
var _v$10 = !!(msg().kind === "success"), _v$11 = !!(msg().kind === "error");
|
|
8198
|
+
_v$10 !== _p$.e && _el$124.classList.toggle("success", _p$.e = _v$10);
|
|
8199
|
+
_v$11 !== _p$.t && _el$124.classList.toggle("error", _p$.t = _v$11);
|
|
8154
8200
|
return _p$;
|
|
8155
8201
|
}, {
|
|
8156
8202
|
e: void 0,
|
|
@@ -8312,9 +8358,9 @@ const Settings = () => {
|
|
|
8312
8358
|
var _el$132 = _tmpl$29();
|
|
8313
8359
|
insert(_el$132, () => msg().text);
|
|
8314
8360
|
createRenderEffect((_p$) => {
|
|
8315
|
-
var _v$
|
|
8316
|
-
_v$
|
|
8317
|
-
_v$
|
|
8361
|
+
var _v$12 = !!(msg().kind === "success"), _v$13 = !!(msg().kind === "error");
|
|
8362
|
+
_v$12 !== _p$.e && _el$132.classList.toggle("success", _p$.e = _v$12);
|
|
8363
|
+
_v$13 !== _p$.t && _el$132.classList.toggle("error", _p$.t = _v$13);
|
|
8318
8364
|
return _p$;
|
|
8319
8365
|
}, {
|
|
8320
8366
|
e: void 0,
|
|
@@ -8336,9 +8382,9 @@ const Settings = () => {
|
|
|
8336
8382
|
var _el$133 = _tmpl$29();
|
|
8337
8383
|
insert(_el$133, () => currentStatus().text);
|
|
8338
8384
|
createRenderEffect((_p$) => {
|
|
8339
|
-
var _v$
|
|
8340
|
-
_v$
|
|
8341
|
-
_v$
|
|
8385
|
+
var _v$14 = !!(currentStatus().kind === "success"), _v$15 = !!(currentStatus().kind === "error");
|
|
8386
|
+
_v$14 !== _p$.e && _el$133.classList.toggle("success", _p$.e = _v$14);
|
|
8387
|
+
_v$15 !== _p$.t && _el$133.classList.toggle("error", _p$.t = _v$15);
|
|
8342
8388
|
return _p$;
|
|
8343
8389
|
}, {
|
|
8344
8390
|
e: void 0,
|
|
@@ -8348,15 +8394,16 @@ const Settings = () => {
|
|
|
8348
8394
|
})()
|
|
8349
8395
|
}), null);
|
|
8350
8396
|
createRenderEffect((_p$) => {
|
|
8351
|
-
var _v$ = !!
|
|
8352
|
-
_v$ !== _p$.e && _el
|
|
8353
|
-
_v$2 !== _p$.t &&
|
|
8354
|
-
_v$3 !== _p$.a && _el$
|
|
8355
|
-
_v$4 !== _p$.o &&
|
|
8356
|
-
_v$5 !== _p$.i && _el$
|
|
8357
|
-
_v$6 !== _p$.n &&
|
|
8358
|
-
_v$7 !== _p$.s && _el$
|
|
8359
|
-
_v$8 !== _p$.h &&
|
|
8397
|
+
var _v$ = !!settingsClosing(), _v$2 = !!autoRestoreSession(), _v$3 = autoRestoreSession(), _v$4 = !!clearBookmarksOnLaunch(), _v$5 = clearBookmarksOnLaunch(), _v$6 = !!chatEnabled(), _v$7 = chatEnabled(), _v$8 = !!telemetryEnabled(), _v$9 = telemetryEnabled();
|
|
8398
|
+
_v$ !== _p$.e && _el$.classList.toggle("closing", _p$.e = _v$);
|
|
8399
|
+
_v$2 !== _p$.t && _el$36.classList.toggle("on", _p$.t = _v$2);
|
|
8400
|
+
_v$3 !== _p$.a && setAttribute(_el$36, "aria-checked", _p$.a = _v$3);
|
|
8401
|
+
_v$4 !== _p$.o && _el$39.classList.toggle("on", _p$.o = _v$4);
|
|
8402
|
+
_v$5 !== _p$.i && setAttribute(_el$39, "aria-checked", _p$.i = _v$5);
|
|
8403
|
+
_v$6 !== _p$.n && _el$43.classList.toggle("on", _p$.n = _v$6);
|
|
8404
|
+
_v$7 !== _p$.s && setAttribute(_el$43, "aria-checked", _p$.s = _v$7);
|
|
8405
|
+
_v$8 !== _p$.h && _el$93.classList.toggle("on", _p$.h = _v$8);
|
|
8406
|
+
_v$9 !== _p$.r && setAttribute(_el$93, "aria-checked", _p$.r = _v$9);
|
|
8360
8407
|
return _p$;
|
|
8361
8408
|
}, {
|
|
8362
8409
|
e: void 0,
|
|
@@ -8366,7 +8413,8 @@ const Settings = () => {
|
|
|
8366
8413
|
i: void 0,
|
|
8367
8414
|
n: void 0,
|
|
8368
8415
|
s: void 0,
|
|
8369
|
-
h: void 0
|
|
8416
|
+
h: void 0,
|
|
8417
|
+
r: void 0
|
|
8370
8418
|
});
|
|
8371
8419
|
createRenderEffect(() => _el$20.value = defaultUrl());
|
|
8372
8420
|
createRenderEffect(() => _el$23.value = mcpPort());
|
|
@@ -8391,6 +8439,9 @@ var _tmpl$$1 = /* @__PURE__ */ template(`<div class=command-bar-overlay><div cla
|
|
|
8391
8439
|
inset 0 1px 0 rgba(255, 255, 255, 0.04);
|
|
8392
8440
|
animation: command-bar-enter 350ms var(--ease-out-expo) both;
|
|
8393
8441
|
}
|
|
8442
|
+
.command-bar-overlay.closing .keyboard-help {
|
|
8443
|
+
animation: command-bar-exit 200ms var(--ease-in-out) both;
|
|
8444
|
+
}
|
|
8394
8445
|
.keyboard-help-header {
|
|
8395
8446
|
display: flex;
|
|
8396
8447
|
justify-content: space-between;
|
|
@@ -8487,9 +8538,13 @@ const SHORTCUTS = [{
|
|
|
8487
8538
|
action: "This help overlay"
|
|
8488
8539
|
}];
|
|
8489
8540
|
const KeyboardHelp = (props) => {
|
|
8541
|
+
const {
|
|
8542
|
+
visible,
|
|
8543
|
+
closing
|
|
8544
|
+
} = useAnimatedPresence(() => props.open, 200);
|
|
8490
8545
|
return createComponent(Show, {
|
|
8491
8546
|
get when() {
|
|
8492
|
-
return
|
|
8547
|
+
return visible();
|
|
8493
8548
|
},
|
|
8494
8549
|
get children() {
|
|
8495
8550
|
return [(() => {
|
|
@@ -8510,6 +8565,7 @@ const KeyboardHelp = (props) => {
|
|
|
8510
8565
|
insert(_el$9, () => s.action);
|
|
8511
8566
|
return _el$9;
|
|
8512
8567
|
})()]));
|
|
8568
|
+
createRenderEffect(() => _el$.classList.toggle("closing", !!closing()));
|
|
8513
8569
|
return _el$;
|
|
8514
8570
|
})(), _tmpl$2$1()];
|
|
8515
8571
|
}
|
|
@@ -8589,28 +8645,7 @@ const App = () => {
|
|
|
8589
8645
|
} = useTabs();
|
|
8590
8646
|
const [highlightToast, setHighlightToast] = createSignal(null);
|
|
8591
8647
|
const [keyboardHelpOpen, setKeyboardHelpOpen] = createSignal(false);
|
|
8592
|
-
const
|
|
8593
|
-
try {
|
|
8594
|
-
const result = await window.vessel.highlights.capture();
|
|
8595
|
-
if (result.success && result.text) {
|
|
8596
|
-
const preview = result.text.length > 60 ? result.text.slice(0, 57) + "..." : result.text;
|
|
8597
|
-
setHighlightToast({
|
|
8598
|
-
title: "Highlight saved",
|
|
8599
|
-
message: preview
|
|
8600
|
-
});
|
|
8601
|
-
} else {
|
|
8602
|
-
setHighlightToast({
|
|
8603
|
-
title: "No selection",
|
|
8604
|
-
message: result.message || "Select text on the page first, then press Ctrl+H"
|
|
8605
|
-
});
|
|
8606
|
-
}
|
|
8607
|
-
} catch {
|
|
8608
|
-
setHighlightToast({
|
|
8609
|
-
title: "Highlight failed",
|
|
8610
|
-
message: "Could not capture selection"
|
|
8611
|
-
});
|
|
8612
|
-
}
|
|
8613
|
-
};
|
|
8648
|
+
const loadingPresence = useAnimatedPresence(() => !!activeTab()?.isLoading, 300);
|
|
8614
8649
|
const showHighlightResult = (result) => {
|
|
8615
8650
|
if (result.success && result.text) {
|
|
8616
8651
|
const preview = result.text.length > 60 ? result.text.slice(0, 57) + "..." : result.text;
|
|
@@ -8625,6 +8660,17 @@ const App = () => {
|
|
|
8625
8660
|
});
|
|
8626
8661
|
}
|
|
8627
8662
|
};
|
|
8663
|
+
const captureHighlight = async () => {
|
|
8664
|
+
try {
|
|
8665
|
+
const result = await window.vessel.highlights.capture();
|
|
8666
|
+
showHighlightResult(result);
|
|
8667
|
+
} catch {
|
|
8668
|
+
setHighlightToast({
|
|
8669
|
+
title: "Highlight failed",
|
|
8670
|
+
message: "Could not capture selection"
|
|
8671
|
+
});
|
|
8672
|
+
}
|
|
8673
|
+
};
|
|
8628
8674
|
onMount(() => {
|
|
8629
8675
|
if (view !== "chrome") return;
|
|
8630
8676
|
const cleanupKeys = setupKeybindings({
|
|
@@ -8672,10 +8718,12 @@ const App = () => {
|
|
|
8672
8718
|
insert(_el$2, createComponent(AddressBar, {}), null);
|
|
8673
8719
|
insert(_el$2, createComponent(Show, {
|
|
8674
8720
|
get when() {
|
|
8675
|
-
return
|
|
8721
|
+
return loadingPresence.visible();
|
|
8676
8722
|
},
|
|
8677
8723
|
get children() {
|
|
8678
|
-
|
|
8724
|
+
var _el$3 = _tmpl$();
|
|
8725
|
+
createRenderEffect(() => _el$3.classList.toggle("closing", !!loadingPresence.closing()));
|
|
8726
|
+
return _el$3;
|
|
8679
8727
|
}
|
|
8680
8728
|
}), null);
|
|
8681
8729
|
insert(_el$, createComponent(CommandBar, {}), null);
|
|
@@ -177,6 +177,24 @@
|
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
.tab-item.closing {
|
|
181
|
+
animation: tab-close 200ms var(--ease-in-out) both;
|
|
182
|
+
pointer-events: none;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
@keyframes tab-close {
|
|
186
|
+
from {
|
|
187
|
+
max-width: 200px;
|
|
188
|
+
padding: 0 12px;
|
|
189
|
+
opacity: 1;
|
|
190
|
+
}
|
|
191
|
+
to {
|
|
192
|
+
max-width: 0;
|
|
193
|
+
padding: 0;
|
|
194
|
+
opacity: 0;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
180
198
|
.tab-item:hover {
|
|
181
199
|
background: rgba(255, 255, 255, 0.04);
|
|
182
200
|
color: var(--text-secondary);
|
|
@@ -585,17 +603,6 @@
|
|
|
585
603
|
animation: badge-enter var(--duration-enter) var(--ease-out-back) both;
|
|
586
604
|
}
|
|
587
605
|
|
|
588
|
-
@keyframes badge-enter {
|
|
589
|
-
from {
|
|
590
|
-
opacity: 0;
|
|
591
|
-
transform: scale(0);
|
|
592
|
-
}
|
|
593
|
-
to {
|
|
594
|
-
opacity: 1;
|
|
595
|
-
transform: scale(1);
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
|
|
599
606
|
|
|
600
607
|
/* ═══════════════════════════════════════
|
|
601
608
|
Bookmark toast notifications — animated
|
|
@@ -941,6 +948,30 @@
|
|
|
941
948
|
}
|
|
942
949
|
}
|
|
943
950
|
|
|
951
|
+
@keyframes command-bar-exit {
|
|
952
|
+
from {
|
|
953
|
+
opacity: 1;
|
|
954
|
+
transform: translateY(0) scale(1);
|
|
955
|
+
}
|
|
956
|
+
to {
|
|
957
|
+
opacity: 0;
|
|
958
|
+
transform: translateY(-12px) scale(0.97);
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
@keyframes overlay-fade-out {
|
|
963
|
+
from { opacity: 1; }
|
|
964
|
+
to { opacity: 0; }
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
.command-bar-overlay.closing {
|
|
968
|
+
animation: overlay-fade-out 200ms var(--ease-in-out) both;
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
.command-bar-overlay.closing .command-bar {
|
|
972
|
+
animation: command-bar-exit 200ms var(--ease-in-out) both;
|
|
973
|
+
}
|
|
974
|
+
|
|
944
975
|
.command-bar form {
|
|
945
976
|
display: flex;
|
|
946
977
|
align-items: center;
|
|
@@ -1307,17 +1338,6 @@
|
|
|
1307
1338
|
animation: badge-enter var(--duration-enter) var(--ease-out-back) both;
|
|
1308
1339
|
}
|
|
1309
1340
|
|
|
1310
|
-
@keyframes badge-enter {
|
|
1311
|
-
from {
|
|
1312
|
-
opacity: 0;
|
|
1313
|
-
transform: scale(0);
|
|
1314
|
-
}
|
|
1315
|
-
to {
|
|
1316
|
-
opacity: 1;
|
|
1317
|
-
transform: scale(1);
|
|
1318
|
-
}
|
|
1319
|
-
}
|
|
1320
|
-
|
|
1321
1341
|
.sidebar-messages {
|
|
1322
1342
|
flex: 1;
|
|
1323
1343
|
overflow-y: auto;
|
|
@@ -4543,6 +4563,11 @@ button:active:not(:disabled) {
|
|
|
4543
4563
|
loading-bar-enter var(--duration-normal) var(--ease-out-expo) both,
|
|
4544
4564
|
loading-bar-shimmer 1.6s ease-in-out infinite;
|
|
4545
4565
|
z-index: 10;
|
|
4566
|
+
transition: opacity 300ms var(--ease-in-out);
|
|
4567
|
+
}
|
|
4568
|
+
|
|
4569
|
+
.loading-bar.closing {
|
|
4570
|
+
opacity: 0;
|
|
4546
4571
|
}
|
|
4547
4572
|
|
|
4548
4573
|
@keyframes loading-bar-enter {
|
|
@@ -4677,3 +4702,14 @@ button:active:not(:disabled) {
|
|
|
4677
4702
|
[data-tooltip-pos="left"]:hover::after {
|
|
4678
4703
|
transform: translateY(-50%) translateX(0);
|
|
4679
4704
|
}
|
|
4705
|
+
|
|
4706
|
+
@keyframes badge-enter {
|
|
4707
|
+
from {
|
|
4708
|
+
opacity: 0;
|
|
4709
|
+
transform: scale(0);
|
|
4710
|
+
}
|
|
4711
|
+
to {
|
|
4712
|
+
opacity: 1;
|
|
4713
|
+
transform: scale(1);
|
|
4714
|
+
}
|
|
4715
|
+
}
|
package/out/renderer/index.html
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
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-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
8
|
+
<script type="module" crossorigin src="./assets/index-DVD9XuhC.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="./assets/index-eS3ccAls.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|
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.30",
|
|
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": {
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"typecheck": "tsc --noEmit",
|
|
25
25
|
"prepublishOnly": "npm run build",
|
|
26
26
|
"test:navigation-regression": "env -u ELECTRON_RUN_AS_NODE ELECTRON_DISABLE_SANDBOX=1 electron --no-sandbox --disable-setuid-sandbox scripts/run-navigation-regression.mjs",
|
|
27
|
+
"test:mcp-proxy": "node scripts/test-mcp-stdio-proxy.mjs",
|
|
27
28
|
"smoke:test": "node scripts/smoke-test.mjs",
|
|
28
29
|
"test:coverage": "c8 --reporter=text --reporter=html tsx --test tests/*.test.ts"
|
|
29
30
|
},
|