blun-king-cli 5.3.1 → 5.3.3
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/blun-cli.js +135 -12
- package/browser-controller.js +3 -1
- package/package.json +1 -1
package/blun-cli.js
CHANGED
|
@@ -564,6 +564,10 @@ async function handleCommand(input) {
|
|
|
564
564
|
await cmdRender(args);
|
|
565
565
|
break;
|
|
566
566
|
|
|
567
|
+
case "/browser":
|
|
568
|
+
await cmdBrowser(args);
|
|
569
|
+
break;
|
|
570
|
+
|
|
567
571
|
case "/exit":
|
|
568
572
|
case "/quit":
|
|
569
573
|
case "/q":
|
|
@@ -1708,27 +1712,111 @@ async function cmdAgent(args) {
|
|
|
1708
1712
|
async function cmdScreenshot(args) {
|
|
1709
1713
|
if (!args) { printError("Usage: /screenshot <url>"); return; }
|
|
1710
1714
|
try {
|
|
1711
|
-
|
|
1712
|
-
var
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1715
|
+
// Try local Playwright first
|
|
1716
|
+
var browser = null;
|
|
1717
|
+
try { browser = require(path.join(__dirname, "browser-controller")); } catch(e) {}
|
|
1718
|
+
if (!browser) {
|
|
1719
|
+
try { browser = require("playwright"); } catch(e) {}
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
if (browser && browser.open) {
|
|
1723
|
+
printInfo("Opening " + args + " (local Playwright)...");
|
|
1724
|
+
var snap = await browser.open(args);
|
|
1725
|
+
var shotPath = path.join(config.workdir, "screenshot-" + Date.now() + ".png");
|
|
1726
|
+
await browser.screenshot(shotPath);
|
|
1727
|
+
printSuccess("Screenshot saved: " + shotPath);
|
|
1728
|
+
console.log(" " + C.gray + "Title: " + C.reset + snap.title);
|
|
1729
|
+
console.log(" " + C.gray + "URL: " + C.reset + snap.url);
|
|
1730
|
+
console.log("");
|
|
1731
|
+
} else {
|
|
1732
|
+
// Fallback to server API
|
|
1733
|
+
printInfo("Taking screenshot via server...");
|
|
1734
|
+
var resp = await apiCall("POST", "/screenshot", { url: args });
|
|
1735
|
+
if (resp.status !== 200) { printError(resp.data.error || "Error"); return; }
|
|
1736
|
+
printSuccess("Screenshot: " + resp.data.title);
|
|
1737
|
+
console.log(" Download: " + C.brightCyan + config.api.base_url + resp.data.screenshot + C.reset);
|
|
1738
|
+
console.log("");
|
|
1739
|
+
}
|
|
1717
1740
|
} catch(e) { printError(e.message); }
|
|
1718
1741
|
}
|
|
1719
1742
|
|
|
1720
1743
|
async function cmdRender(args) {
|
|
1721
1744
|
if (!args) { printError("Usage: /render <url>"); return; }
|
|
1722
1745
|
try {
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1746
|
+
var browser = null;
|
|
1747
|
+
try { browser = require(path.join(__dirname, "browser-controller")); } catch(e) {}
|
|
1748
|
+
|
|
1749
|
+
if (browser && browser.open) {
|
|
1750
|
+
printInfo("Rendering " + args + " (local Playwright)...");
|
|
1751
|
+
var snap = await browser.open(args);
|
|
1752
|
+
printSuccess("Rendered: " + snap.title);
|
|
1753
|
+
console.log(" " + C.gray + "URL: " + C.reset + snap.url);
|
|
1754
|
+
if (snap.text) {
|
|
1755
|
+
console.log(C.dim + " " + BOX.h.repeat(40) + C.reset);
|
|
1756
|
+
console.log(" " + snap.text.slice(0, 500));
|
|
1757
|
+
}
|
|
1758
|
+
console.log("");
|
|
1759
|
+
} else {
|
|
1760
|
+
printInfo("Rendering " + args + " via server...");
|
|
1761
|
+
var resp = await apiCall("POST", "/render", { url: args });
|
|
1762
|
+
if (resp.status !== 200) { printError(resp.data.error || "Error"); return; }
|
|
1763
|
+
printSuccess("Rendered: " + resp.data.title + " (" + resp.data.html_length + " chars)");
|
|
1764
|
+
if (resp.data.screenshot) console.log(" Screenshot: " + C.brightCyan + resp.data.screenshot + C.reset);
|
|
1765
|
+
console.log("");
|
|
1766
|
+
}
|
|
1729
1767
|
} catch(e) { printError(e.message); }
|
|
1730
1768
|
}
|
|
1731
1769
|
|
|
1770
|
+
// ── Browser Control Commands ──
|
|
1771
|
+
async function cmdBrowser(args) {
|
|
1772
|
+
var browser = null;
|
|
1773
|
+
try { browser = require(path.join(__dirname, "browser-controller")); } catch(e) {}
|
|
1774
|
+
if (!browser) {
|
|
1775
|
+
printError("Playwright not available. Run: npx playwright install chromium");
|
|
1776
|
+
return;
|
|
1777
|
+
}
|
|
1778
|
+
var parts = (args || "").split(/\s+/);
|
|
1779
|
+
var action = parts[0] || "help";
|
|
1780
|
+
|
|
1781
|
+
try {
|
|
1782
|
+
if (action === "open" && parts[1]) {
|
|
1783
|
+
printInfo("Opening " + parts[1] + "...");
|
|
1784
|
+
var snap = await browser.open(parts[1]);
|
|
1785
|
+
printSuccess(snap.title + " — " + snap.url);
|
|
1786
|
+
} else if (action === "click" && parts[1]) {
|
|
1787
|
+
var snap = await browser.click(parts.slice(1).join(" "));
|
|
1788
|
+
printSuccess("Clicked. Now at: " + snap.url);
|
|
1789
|
+
} else if (action === "type" && parts[1]) {
|
|
1790
|
+
var selector = parts[1];
|
|
1791
|
+
var text = parts.slice(2).join(" ");
|
|
1792
|
+
var snap = await browser.type(selector, text);
|
|
1793
|
+
printSuccess("Typed into " + selector);
|
|
1794
|
+
} else if (action === "screenshot") {
|
|
1795
|
+
var shotPath = parts[1] || path.join(config.workdir, "screenshot-" + Date.now() + ".png");
|
|
1796
|
+
await browser.screenshot(shotPath);
|
|
1797
|
+
printSuccess("Screenshot: " + shotPath);
|
|
1798
|
+
} else if (action === "snap" || action === "snapshot") {
|
|
1799
|
+
var snap = await browser.snapshot();
|
|
1800
|
+
console.log(C.gray + " URL: " + C.reset + snap.url);
|
|
1801
|
+
console.log(C.gray + " Title: " + C.reset + snap.title);
|
|
1802
|
+
if (snap.text) console.log(" " + snap.text.slice(0, 300));
|
|
1803
|
+
} else if (action === "close") {
|
|
1804
|
+
await browser.close();
|
|
1805
|
+
printSuccess("Browser closed.");
|
|
1806
|
+
} else {
|
|
1807
|
+
console.log("");
|
|
1808
|
+
console.log(C.bold + " Browser Commands:" + C.reset);
|
|
1809
|
+
console.log(" /browser open <url> Open a URL");
|
|
1810
|
+
console.log(" /browser click <selector> Click an element");
|
|
1811
|
+
console.log(" /browser type <sel> <text> Type text into element");
|
|
1812
|
+
console.log(" /browser screenshot [path] Take screenshot");
|
|
1813
|
+
console.log(" /browser snap Get page text snapshot");
|
|
1814
|
+
console.log(" /browser close Close browser");
|
|
1815
|
+
console.log("");
|
|
1816
|
+
}
|
|
1817
|
+
} catch(browserErr) { printError("Browser error: " + browserErr.message); }
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1732
1820
|
// ══════════════════════════════════════════════════
|
|
1733
1821
|
// ── 1. SETTINGS REGISTRY (Multi-Scope) ──
|
|
1734
1822
|
// ══════════════════════════════════════════════════
|
|
@@ -2976,7 +3064,41 @@ async function main() {
|
|
|
2976
3064
|
await handleCommand(input);
|
|
2977
3065
|
runHook("post", input.split(/\s+/)[0].slice(1));
|
|
2978
3066
|
} else {
|
|
3067
|
+
// Browser intent — natural language with URL → local Playwright
|
|
3068
|
+
var urlMatch = input.match(/(https?:\/\/\S+)/i);
|
|
3069
|
+
var browserWords = /\b(öffne|open|schau|zeig|geh auf|navigate|browse|screenshot|bildschirmfoto|aufrufen|besuch|check|prüf|analysier)\b/i;
|
|
3070
|
+
if (urlMatch && browserWords.test(input)) {
|
|
3071
|
+
var browserUrl = urlMatch[1];
|
|
3072
|
+
try {
|
|
3073
|
+
var bc = require(path.join(__dirname, "browser-controller"));
|
|
3074
|
+
if (/screenshot|bildschirmfoto/i.test(input)) {
|
|
3075
|
+
printInfo("Screenshot: " + browserUrl);
|
|
3076
|
+
var snap = await bc.open(browserUrl);
|
|
3077
|
+
var shotFile = path.join(config.workdir, "screenshot-" + Date.now() + ".png");
|
|
3078
|
+
await bc.screenshot(shotFile);
|
|
3079
|
+
printSuccess("Screenshot gespeichert: " + shotFile);
|
|
3080
|
+
console.log(" " + C.gray + "Title: " + C.reset + snap.title);
|
|
3081
|
+
} else {
|
|
3082
|
+
printInfo("Öffne " + browserUrl + "...");
|
|
3083
|
+
var snap = await bc.open(browserUrl);
|
|
3084
|
+
printSuccess(snap.title);
|
|
3085
|
+
console.log(" " + C.gray + "URL: " + C.reset + snap.url);
|
|
3086
|
+
if (snap.text) {
|
|
3087
|
+
console.log(C.dim + " " + BOX.h.repeat(40) + C.reset);
|
|
3088
|
+
var preview = snap.text.slice(0, 500).replace(/\n{3,}/g, "\n\n");
|
|
3089
|
+
console.log(" " + preview);
|
|
3090
|
+
}
|
|
3091
|
+
console.log("");
|
|
3092
|
+
// Send page context to chat so BLUN King can discuss it
|
|
3093
|
+
await sendChat(input + "\n\n[Browser-Kontext: " + snap.title + " — " + snap.text.slice(0, 1000) + "]");
|
|
3094
|
+
}
|
|
3095
|
+
} catch(bcErr) {
|
|
3096
|
+
// Playwright not available, send to chat normally
|
|
3097
|
+
await sendChat(input);
|
|
3098
|
+
}
|
|
3099
|
+
}
|
|
2979
3100
|
// Intent detection — natural language → command
|
|
3101
|
+
else {
|
|
2980
3102
|
var detected = detectIntent(input);
|
|
2981
3103
|
if (detected) {
|
|
2982
3104
|
printInfo("→ " + detected);
|
|
@@ -2998,6 +3120,7 @@ async function main() {
|
|
|
2998
3120
|
} else {
|
|
2999
3121
|
await sendChat(input);
|
|
3000
3122
|
}
|
|
3123
|
+
}
|
|
3001
3124
|
}
|
|
3002
3125
|
|
|
3003
3126
|
inputBuffer = "";
|
package/browser-controller.js
CHANGED
|
@@ -15,7 +15,9 @@ async function ensurePage() {
|
|
|
15
15
|
|
|
16
16
|
async function open(url) {
|
|
17
17
|
const page = await ensurePage();
|
|
18
|
-
|
|
18
|
+
var cleanUrl = String(url).replace(/^<|>$/g, "").trim();
|
|
19
|
+
if (!/^https?:\/\//i.test(cleanUrl)) cleanUrl = "https://" + cleanUrl;
|
|
20
|
+
await page.goto(cleanUrl, { waitUntil: "domcontentloaded", timeout: 30000 });
|
|
19
21
|
return snapshot();
|
|
20
22
|
}
|
|
21
23
|
|