fluxflow-cli 1.5.1 → 1.5.2

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.
Files changed (2) hide show
  1. package/dist/fluxflow.js +92 -76
  2. package/package.json +2 -3
package/dist/fluxflow.js CHANGED
@@ -980,7 +980,7 @@ var init_arg_parser = __esm({
980
980
  });
981
981
 
982
982
  // src/tools/web_search.js
983
- import * as cuimp from "cuimp";
983
+ import puppeteer from "puppeteer";
984
984
  import fs6 from "fs";
985
985
  import path6 from "path";
986
986
  var web_search;
@@ -994,74 +994,80 @@ var init_web_search = __esm({
994
994
  const maxRetries = 3;
995
995
  let lastError = null;
996
996
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
997
+ let browser = null;
997
998
  try {
998
- const userAgents = [
999
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
1000
- "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
1001
- "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
1002
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0"
1003
- ];
1004
- const randomUA = userAgents[Math.floor(Math.random() * userAgents.length)];
999
+ browser = await puppeteer.launch({
1000
+ headless: true,
1001
+ args: [
1002
+ "--no-sandbox",
1003
+ "--disable-setuid-sandbox",
1004
+ "--disable-gpu",
1005
+ "--disable-dev-shm-usage"
1006
+ ]
1007
+ });
1008
+ const page = await browser.newPage();
1009
+ await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36");
1010
+ await page.setViewport({ width: 1280, height: 800 });
1005
1011
  const jitter = attempt === 1 ? Math.random() * 1e3 + 500 : Math.random() * 2e3 + 1e3;
1006
1012
  await new Promise((r) => setTimeout(r, jitter));
1007
- const response = await cuimp.get(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`, {
1008
- headers: {
1009
- "User-Agent": randomUA,
1010
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
1011
- "Accept-Language": "en-US,en;q=0.9",
1012
- "Referer": "https://duckduckgo.com/",
1013
- "Upgrade-Insecure-Requests": "1",
1014
- "Cache-Control": "max-age=0"
1015
- }
1016
- });
1017
- const html = response.data;
1018
- const results = [];
1019
- const resultRegex = /<a[^>]*class="result__a"[^>]*href="([^"]+)"[^>]*>([\s\S]*?)<\/a>[\s\S]*?<a[^>]*class="result__snippet"[^>]*>([\s\S]*?)<\/a>/g;
1020
- let match;
1021
- let count = 0;
1022
- while ((match = resultRegex.exec(html)) !== null && count < limit) {
1023
- let url = match[1];
1024
- if (url.includes("uddg=")) {
1025
- url = decodeURIComponent(url.split("uddg=")[1].split("&")[0]);
1026
- }
1027
- const title = match[2].replace(/<[^>]*>/g, "").trim();
1028
- const snippet = match[3].replace(/<[^>]*>/g, "").trim();
1029
- results.push(`${count + 1}. ${title}
1013
+ const searchUrl = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`;
1014
+ await page.goto(searchUrl, { waitUntil: "networkidle2" });
1015
+ const results = await page.$$eval(".result", (elements, maxLimit) => {
1016
+ return elements.slice(0, maxLimit).map((el, i) => {
1017
+ const titleEl = el.querySelector(".result__a");
1018
+ const snippetEl = el.querySelector(".result__snippet");
1019
+ let url = titleEl ? titleEl.href : "";
1020
+ if (url.includes("uddg=")) {
1021
+ url = decodeURIComponent(url.split("uddg=")[1].split("&")[0]);
1022
+ }
1023
+ const title = titleEl ? titleEl.innerText.trim() : "No Title";
1024
+ const snippet = snippetEl ? snippetEl.innerText.trim() : "No Snippet";
1025
+ return `${i + 1}. ${title}
1030
1026
  Source: ${url}
1031
- Snippet: ${snippet}`);
1032
- count++;
1033
- }
1027
+ Snippet: ${snippet}`;
1028
+ });
1029
+ }, limit);
1034
1030
  if (results.length === 0) {
1035
- if (html.includes("anomaly")) {
1036
- throw new Error("DDG_ANOMALY_DETECTED");
1031
+ const bodyText = await page.evaluate(() => document.body.innerText);
1032
+ if (bodyText.includes("anomaly")) {
1033
+ throw new Error("ANOMALY_DETECTED");
1037
1034
  }
1035
+ await browser.close();
1038
1036
  return `No results found for query: [${query}].`;
1039
1037
  }
1040
1038
  const finalResults = results.join("\n\n");
1039
+ const toolLogDir = path6.join(LOGS_DIR, "tools");
1040
+ if (!fs6.existsSync(toolLogDir)) fs6.mkdirSync(toolLogDir, { recursive: true });
1041
+ fs6.appendFileSync(path6.join(toolLogDir, "search-results.log"), `SEARCH ${(/* @__PURE__ */ new Date()).toISOString()} - Query: [${query}]. Count: ${results.length}.
1042
+ Content:
1043
+ ${finalResults}
1044
+
1045
+ --------------------------------------------------------
1046
+
1047
+
1048
+ `);
1049
+ await browser.close();
1041
1050
  return `Search results for [${query}]:
1042
1051
 
1043
1052
  ${finalResults}`;
1044
1053
  } catch (err) {
1045
1054
  lastError = err;
1046
- const toolErrDir = path6.join(LOGS_DIR, "tools");
1047
- if (!fs6.existsSync(toolErrDir)) fs6.mkdirSync(toolErrDir, { recursive: true });
1048
- fs6.appendFileSync(path6.join(toolErrDir, "error.log"), `ERROR ${(/* @__PURE__ */ new Date()).toISOString()} - Attempt ${attempt}/${maxRetries} failed: ${err.message}
1049
- `);
1055
+ if (browser) await browser.close();
1050
1056
  if (attempt < maxRetries) {
1051
1057
  const backoff = Math.pow(2, attempt) * 1e3;
1052
1058
  await new Promise((r) => setTimeout(r, backoff));
1053
1059
  }
1054
1060
  }
1055
1061
  }
1056
- return `ERROR: Search failed after ${maxRetries} attempts. Last error: ${lastError.message}`;
1062
+ return `ERROR: Search failed after ${maxRetries + 1} attempts. Last error: ${lastError.message}`;
1057
1063
  };
1058
1064
  }
1059
1065
  });
1060
1066
 
1061
1067
  // src/tools/web_scrape.js
1068
+ import puppeteer2 from "puppeteer";
1062
1069
  import fs7 from "fs";
1063
1070
  import path7 from "path";
1064
- import * as cuimp2 from "cuimp";
1065
1071
  var web_scrape;
1066
1072
  var init_web_scrape = __esm({
1067
1073
  "src/tools/web_scrape.js"() {
@@ -1072,53 +1078,63 @@ var init_web_scrape = __esm({
1072
1078
  const maxRetries = 3;
1073
1079
  let lastError = null;
1074
1080
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
1081
+ let browser = null;
1075
1082
  try {
1076
- const userAgents = [
1077
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
1078
- "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
1079
- "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
1080
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0"
1081
- ];
1082
- const randomUA = userAgents[Math.floor(Math.random() * userAgents.length)];
1083
+ browser = await puppeteer2.launch({
1084
+ headless: true,
1085
+ args: [
1086
+ "--no-sandbox",
1087
+ "--disable-setuid-sandbox",
1088
+ "--disable-gpu",
1089
+ "--disable-dev-shm-usage"
1090
+ ]
1091
+ });
1092
+ const page = await browser.newPage();
1093
+ await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36");
1094
+ await page.setViewport({ width: 1280, height: 1600 });
1083
1095
  const jitter = attempt === 1 ? Math.random() * 1e3 + 500 : Math.random() * 2e3 + 1e3;
1084
1096
  await new Promise((r) => setTimeout(r, jitter));
1085
- const response = await cuimp2.get(url, {
1086
- headers: {
1087
- "User-Agent": randomUA,
1088
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
1089
- "Accept-Language": "en-US,en;q=0.9",
1090
- "Referer": "https://www.google.com/",
1091
- "Upgrade-Insecure-Requests": "1",
1092
- "Cache-Control": "max-age=0"
1093
- }
1097
+ await page.goto(url, { waitUntil: "networkidle2", timeout: 45e3 });
1098
+ await new Promise((r) => setTimeout(r, 5e3));
1099
+ let text = await page.evaluate(() => {
1100
+ const junk = document.querySelectorAll("script, style, nav, footer, header, noscript");
1101
+ junk.forEach((el) => el.remove());
1102
+ const links = document.querySelectorAll("a");
1103
+ links.forEach((a) => {
1104
+ const href = a.href;
1105
+ const content = a.innerText.trim();
1106
+ if (href && content && !href.startsWith("javascript:") && !href.startsWith("#")) {
1107
+ a.innerText = ` [${content}](${href}) `;
1108
+ }
1109
+ });
1110
+ return document.body.innerText;
1094
1111
  });
1095
- let html = response.data;
1096
- if (!html) throw new Error("EMPTY_RESPONSE");
1097
- html = html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "");
1098
- html = html.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, "");
1099
- html = html.replace(/<nav\b[^<]*(?:(?!<\/nav>)<[^<]*)*<\/nav>/gi, "");
1100
- html = html.replace(/<footer\b[^<]*(?:(?!<\/footer>)<[^<]*)*<\/footer>/gi, "");
1101
- html = html.replace(/<header\b[^<]*(?:(?!<\/header>)<[^<]*)*<\/header>/gi, "");
1102
- let text = html.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
1103
- const finalContent = text.substring(0, 2e4);
1112
+ if (!text) throw new Error("EMPTY_RENDER_RESULT");
1113
+ const cleanedText = text.replace(/\s+/g, " ").trim().substring(0, 25e3);
1104
1114
  const toolLogDir = path7.join(LOGS_DIR, "tools");
1105
1115
  if (!fs7.existsSync(toolLogDir)) fs7.mkdirSync(toolLogDir, { recursive: true });
1106
- fs7.appendFileSync(path7.join(toolLogDir, "search-scraped.log"), `RESULTS ${(/* @__PURE__ */ new Date()).toISOString()} -
1107
- URL: [${url}]. Content Length: ${finalContent.length}
1116
+ fs7.appendFileSync(path7.join(toolLogDir, "search-scraped.log"), `PUPPETEER ${(/* @__PURE__ */ new Date()).toISOString()} - URL: [${url}]. Length: ${cleanedText.length}.
1117
+ Content:
1118
+ ${cleanedText}
1119
+
1120
+ --------------------------------------------------------
1121
+
1108
1122
 
1109
1123
  `);
1124
+ await browser.close();
1110
1125
  return `CONTENT FROM [${url}]:
1111
1126
 
1112
- ${finalContent}${text.length > 2e4 ? "\n\n[TRUNCATED AT 20K CHARS]" : ""}`;
1127
+ ${cleanedText}${text.length > 25e3 ? "\n\n[TRUNCATED AT 25K CHARS]" : ""}`;
1113
1128
  } catch (err) {
1114
1129
  lastError = err;
1130
+ if (browser) await browser.close();
1115
1131
  if (attempt < maxRetries) {
1116
1132
  const backoff = Math.pow(2, attempt) * 1e3;
1117
1133
  await new Promise((r) => setTimeout(r, backoff));
1118
1134
  }
1119
1135
  }
1120
1136
  }
1121
- return `ERROR: Scrape failed after ${maxRetries} attempts. Last error: ${lastError.message}`;
1137
+ return `ERROR: Scrape failed after ${maxRetries + 1} attempts. Last error: ${lastError.message}`;
1122
1138
  };
1123
1139
  }
1124
1140
  });
@@ -1667,7 +1683,7 @@ var init_ask_user = __esm({
1667
1683
  });
1668
1684
 
1669
1685
  // src/tools/write_pdf.js
1670
- import puppeteer from "puppeteer";
1686
+ import puppeteer3 from "puppeteer";
1671
1687
  import path13 from "path";
1672
1688
  import fs13 from "fs-extra";
1673
1689
  var write_pdf;
@@ -1682,7 +1698,7 @@ var init_write_pdf = __esm({
1682
1698
  let browser = null;
1683
1699
  try {
1684
1700
  await fs13.ensureDir(path13.dirname(absolutePath));
1685
- browser = await puppeteer.launch({
1701
+ browser = await puppeteer3.launch({
1686
1702
  headless: true,
1687
1703
  args: [
1688
1704
  "--no-sandbox",
@@ -2495,7 +2511,7 @@ var init_UpdateProcessor = __esm({
2495
2511
  });
2496
2512
 
2497
2513
  // src/utils/setup.js
2498
- import puppeteer2 from "puppeteer";
2514
+ import puppeteer4 from "puppeteer";
2499
2515
  import { exec as exec2 } from "child_process";
2500
2516
  import { promisify } from "util";
2501
2517
  import fs16 from "fs";
@@ -2505,7 +2521,7 @@ var init_setup = __esm({
2505
2521
  execAsync = promisify(exec2);
2506
2522
  checkPuppeteerReady = () => {
2507
2523
  try {
2508
- const exePath = puppeteer2.executablePath();
2524
+ const exePath = puppeteer4.executablePath();
2509
2525
  const exists = exePath && fs16.existsSync(exePath);
2510
2526
  if (exists) return true;
2511
2527
  } catch (e) {
@@ -4073,7 +4089,7 @@ var init_app = __esm({
4073
4089
  init_setup();
4074
4090
  SESSION_START_TIME = Date.now();
4075
4091
  CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
4076
- versionFluxflow = "1.5.1";
4092
+ versionFluxflow = "1.5.2";
4077
4093
  updatedOn = "2026-05-01";
4078
4094
  ResolutionModal = ({ data, onResolve, onEdit }) => /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", bold: true, underline: true }, "\u{1F7E3} STEERING HINT RESOLUTION"), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "The agent already finished the task (turn: finish) before your hint was consumed."), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1, backgroundColor: "#222", paddingX: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { italic: true, color: "gray" }, '"', data, '"')), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan" }, "How would you like to proceed?")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
4079
4095
  CommandMenu,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.5.1",
3
+ "version": "1.5.2",
4
4
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
5
5
  "keywords": [
6
6
  "ai",
@@ -34,12 +34,11 @@
34
34
  },
35
35
  "scripts": {
36
36
  "start": "tsx ./src/cli.jsx",
37
- "build": "esbuild ./src/cli.jsx --bundle --platform=node --format=esm --outfile=./dist/fluxflow.js --external:react --external:ink --external:chalk --external:fs-extra --external:gradient-string --external:ink-text-input --external:ink-select-input --external:ink-spinner --external:ink-multiline-input --external:@google/genai --external:zod --external:duck-duck-scrape --external:nanoid --external:cuimp --external:puppeteer --external:typescript"
37
+ "build": "esbuild ./src/cli.jsx --bundle --platform=node --format=esm --outfile=./dist/fluxflow.js --external:react --external:ink --external:chalk --external:fs-extra --external:gradient-string --external:ink-text-input --external:ink-select-input --external:ink-spinner --external:ink-multiline-input --external:@google/genai --external:zod --external:nanoid --external:puppeteer --external:typescript"
38
38
  },
39
39
  "dependencies": {
40
40
  "@google/genai": "^1.50.1",
41
41
  "chalk": "^5.6.2",
42
- "cuimp": "^1.10.0",
43
42
  "fs-extra": "^11.3.4",
44
43
  "gradient-string": "^3.0.0",
45
44
  "ink": "^7.0.1",