fanluc 2.0.0
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/bin/fanluc.js +54 -0
- package/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/dist/assets/_basePickBy-CP3UBwOk.js +1 -0
- package/dist/assets/_baseUniq-CZ8FG28m.js +1 -0
- package/dist/assets/abnfDiagram-O67JEVCF-hiYMdxpV.js +1 -0
- package/dist/assets/arc-DokRg_wy.js +1 -0
- package/dist/assets/architectureDiagram-NJMV4G6O-UzHYe9Bx.js +36 -0
- package/dist/assets/blockDiagram-BEXU5L5S-DqM5UILT.js +140 -0
- package/dist/assets/c4Diagram-YGBWAQC7-Cxkdm7sV.js +38 -0
- package/dist/assets/channel-SPfNTvmj.js +1 -0
- package/dist/assets/chunk-2Q5K7J3B-Nl4zmLlG.js +1 -0
- package/dist/assets/chunk-3FUC2YCW-BCol78O2.js +2 -0
- package/dist/assets/chunk-5VM5RSS4-1u4YRv2Y.js +15 -0
- package/dist/assets/chunk-GTNCS2PH-BG9YIV2h.js +88 -0
- package/dist/assets/chunk-GWA4HPMP-BTKfkJAH.js +1 -0
- package/dist/assets/chunk-JWPE2WC7-DCjElfA7.js +1 -0
- package/dist/assets/chunk-NETBCI7D-QoJORlVn.js +1 -0
- package/dist/assets/chunk-WEXAMYUT-Da-T8ct9.js +1 -0
- package/dist/assets/chunk-XXDRQBXY-CLu69Uei.js +1 -0
- package/dist/assets/classDiagram-v2-NBCMYWYE-DIXavbI9.js +217 -0
- package/dist/assets/cose-bilkent-JH36ORCC-DuWclG8-.js +1 -0
- package/dist/assets/cynefin-OW5HDTMX-D2CG5-xd.js +178 -0
- package/dist/assets/cynefinDiagram-VND7K2PF-goI7_Qfg.js +62 -0
- package/dist/assets/cytoscape.esm-Ix0LnXOy.js +331 -0
- package/dist/assets/dagre-6A5THRUB-BmOaZ0cm.js +4 -0
- package/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/dist/assets/diagram-22UHCM2B-DjDJFMw3.js +200 -0
- package/dist/assets/diagram-3UASUU5V-J6z81NH3.js +24 -0
- package/dist/assets/diagram-ATOU4E4O-B1MPU8ai.js +3 -0
- package/dist/assets/diagram-CDSNMT55-X5Uss0Yv.js +30 -0
- package/dist/assets/diagram-MLGK6HIB-CRDqfYy1.js +24 -0
- package/dist/assets/diagram-MPIPVDR6-bhJtyiOq.js +41 -0
- package/dist/assets/ebnfDiagram-ZINNZB2B-Dn1mZAV8.js +1 -0
- package/dist/assets/elk-276RUBZZ-C93BlBEU.js +27 -0
- package/dist/assets/erDiagram-OPXOYQCR-PuzjAvhD.js +99 -0
- package/dist/assets/flowDiagram-KWPJA3E3-oRhFgO0p.js +213 -0
- package/dist/assets/ganttDiagram-FUAMR5RP-DKiU1XjU.js +292 -0
- package/dist/assets/gitGraphDiagram-X574FWY7-CWBMI0vb.js +106 -0
- package/dist/assets/graph-tGV3vi3M.js +1 -0
- package/dist/assets/index-BylpTP-E.css +1 -0
- package/dist/assets/index-DcpVteR3.js +3237 -0
- package/dist/assets/infoDiagram-VRGFBTTK-C5Hd4Afz.js +2 -0
- package/dist/assets/init-Gi6I4Gst.js +1 -0
- package/dist/assets/ishikawaDiagram-OU5B5YK6-BdD6ulRK.js +70 -0
- package/dist/assets/journeyDiagram-ZHPQQLJL-CzT-uvks.js +139 -0
- package/dist/assets/kanban-definition-PNTS6WVX-BkrazFMR.js +89 -0
- package/dist/assets/katex-C5jXJg4s.js +257 -0
- package/dist/assets/linear-B0wSM1Dr.js +1 -0
- package/dist/assets/mindmap-definition-NLK3R4M7-Df1Acqkf.js +96 -0
- package/dist/assets/ordinal-Cboi1Yqb.js +1 -0
- package/dist/assets/pegDiagram-GJSIUBJH-DK_F7h_0.js +1 -0
- package/dist/assets/permissionHelper--88tJJlz.js +3 -0
- package/dist/assets/pieDiagram-5QR66LMP-BMXyNb9R.js +39 -0
- package/dist/assets/quadrantDiagram-O4NWA36T-Dfu7Z8so.js +7 -0
- package/dist/assets/railroadDiagram-XR7U4H2S-CfnBD-aQ.js +1 -0
- package/dist/assets/requirementDiagram-PLB6GJNP-DrvsZJPP.js +84 -0
- package/dist/assets/sankeyDiagram-IPEJSGJF-DvdVDpT1.js +40 -0
- package/dist/assets/sequenceDiagram-PO4LG4MO-D1UTrvZH.js +169 -0
- package/dist/assets/sizeCapture-INFHLROL-CJrOBcai.js +1 -0
- package/dist/assets/stateDiagram-v2-GCMORJYK-CX8VmtqD.js +291 -0
- package/dist/assets/swimlanes-2SLR337P-DUWmhiK6.js +1 -0
- package/dist/assets/swimlanesDiagram-TC7HE7FX-DMQy1553.js +8 -0
- package/dist/assets/timeline-definition-EJHVYXUP-CBovVdOU.js +120 -0
- package/dist/assets/usecaseDiagram-POWQR4AR-LD5N5BAG.js +370 -0
- package/dist/assets/vennDiagram-UO4OBE2U-DdwfzB3A.js +34 -0
- package/dist/assets/wardleyDiagram-VNRHLVJA-BMHK4bav.js +78 -0
- package/dist/assets/xychartDiagram-PMCCYNJV-q1BNzMC-.js +7 -0
- package/dist/cli.js +474 -0
- package/dist/index.html +18 -0
- package/dist/msh_spin_inverted.gif +0 -0
- package/dist/server.cjs +1974 -0
- package/dist/server.cjs.map +7 -0
- package/dist/shrink_rotate.gif +0 -0
- package/dist/tui.js +5949 -0
- package/docs/fanluc_ui.md +48 -0
- package/docs/guide-connect.md +63 -0
- package/docs/mondk.md +6 -0
- package/docs/msh.md +3 -0
- package/index.html +17 -0
- package/mcp.json +0 -0
- package/package.json +92 -0
- package/public/msh_spin_inverted.gif +0 -0
- package/public/shrink_rotate.gif +0 -0
- package/searxng/docker-compose.yml +20 -0
- package/searxng/settings.yml +23 -0
- package/tsconfig.json +26 -0
- package/vite.config.ts +22 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../server.ts", "../src/utils/decodeText.ts", "../src/core/security/blocklist.ts"],
|
|
4
|
+
"sourcesContent": ["import express from \"express\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport os from \"os\";\nimport { fileURLToPath } from \"url\";\nimport { execFile, execFileSync } from \"child_process\";\nimport { createServer as createViteServer } from \"vite\";\nimport { translate } from \"google-translate-api-x\";\nimport { JSDOM } from \"jsdom\";\nimport { Readability } from \"@mozilla/readability\";\nimport dotenv from \"dotenv\";\nimport dns from \"node:dns/promises\";\nimport net from \"node:net\";\nimport { decodeTextBuffer } from \"./src/utils/decodeText\";\ndotenv.config();\n\nconst IS_WINDOWS = process.platform === \"win32\";\nimport { findBlockedPattern as findBlockedCommand } from \"./src/core/security/blocklist\";\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\n\n// ============================================================================\n// run_cmd \u2014 sandboxed real shell execution (replaces the old browser-only\n// run_js/run_py simulators). This is the one thing on this server that can\n// touch the real filesystem and spawn real processes, so it gets its own\n// layered defenses instead of trusting the AI's text output directly:\n//\n// 1. cwd is hard-pinned to WORKSPACE_DIR for every call (never the app's\n// own source tree, never the real project root) \u2014 a fresh child\n// process each time, so nothing persists across calls except what was\n// actually written to disk in that folder.\n// 2. process.env is replaced with a minimal SAFE_ENV so secrets like\n// GEMINI/API keys in the server's real environment are never visible\n// to a command the AI asked to run (no `env`/`printenv` leak).\n// 3. A regex blocklist rejects the most obviously destructive/exfiltrating\n// patterns before anything is even spawned. This is defense-in-depth,\n// not a airtight sandbox by itself \u2014 see (4).\n// 4. If `firejail` is installed on the host, commands are wrapped in it\n// (--private home jail, --net=none, resource limits) for a real OS\n// level containment boundary. Without firejail, layers 1\u20133 still apply\n// but a truly hostile command run as the server's own OS user could in\n// principle still affect that user's files \u2014 for real Claude-grade\n// isolation, run this whole server inside a Docker container (see\n// docs/run-cmd-security.md) so the \"OS user\" itself is disposable.\n// 5. Hard timeout + output size caps so nothing can hang or flood memory.\n// ============================================================================\n\nfunction resolveWorkspaceDir(): string {\n // CLI sets FANLUC_WORKSPACE to current directory (= workspace is project root)\n // Web fallback is ./workspace subdirectory (existing behavior, no breaking change)\n const override = process.env.FANLUC_WORKSPACE?.trim();\n if (override) return path.resolve(override);\n // Also support legacy WORKSPACE_DIR env for flexibility\n if (process.env.WORKSPACE_DIR?.trim()) return path.resolve(process.env.WORKSPACE_DIR.trim());\n return path.join(process.cwd(), \"workspace\");\n}\n\nexport const WORKSPACE_DIR = resolveWorkspaceDir();\n\nfunction isInsideWorkspace(p: string): boolean {\n const rel = path.relative(WORKSPACE_DIR, path.resolve(p));\n return rel === \"\" || (!rel.startsWith(\"..\") && !path.isAbsolute(rel));\n}\n\ntry {\n fs.mkdirSync(WORKSPACE_DIR, { recursive: true });\n} catch (e) {\n console.error(\"Failed to create workspace dir:\", e);\n}\n\n// Minimal environment handed to every run_cmd child process. Real secrets\n// (GEMINI_API_KEY, etc.) living in the actual server env are deliberately\n// left out so a shell command can never read or exfiltrate them.\nconst SAFE_ENV: NodeJS.ProcessEnv = IS_WINDOWS\n ? {\n PATH: process.env.PATH,\n SystemRoot: process.env.SystemRoot,\n windir: process.env.windir,\n COMSPEC: process.env.COMSPEC,\n OS: process.env.OS,\n SystemDrive: process.env.SystemDrive,\n TEMP: process.env.TEMP,\n TMP: process.env.TMP,\n // On Windows, don't override HOME/USERPROFILE to WORKSPACE_DIR \u2014 that causes\n // PowerShell to create AppData\\Local inside the workspace (polluting project).\n // Keep original USERPROFILE/HOME so profile data stays in real home.\n HOME: process.env.HOME || process.env.USERPROFILE || WORKSPACE_DIR,\n USERPROFILE: process.env.USERPROFILE || process.env.HOME || WORKSPACE_DIR,\n APPDATA: process.env.APPDATA,\n LOCALAPPDATA: process.env.LOCALAPPDATA,\n PYTHONDONTWRITEBYTECODE: \"1\",\n PATHEXT: process.env.PATHEXT,\n LANG: process.env.LANG || \"en_US.UTF-8\",\n }\n : {\n PATH: process.env.PATH,\n HOME: WORKSPACE_DIR,\n LANG: process.env.LANG || \"en_US.UTF-8\",\n PYTHONDONTWRITEBYTECODE: \"1\",\n };\n\n// Permission grants cho ch\u1EBF \u0111\u1ED9 ask/autoEdit (Fix 2) \u2014 in-memory, TTL 5 ph\u00FAt\nlet permissionGrants: { file: number; shell: number } = { file: 0, shell: 0 };\n// TTL m\u1EB7c \u0111\u1ECBnh 5 ph\u00FAt; override b\u1EB1ng FANLUC_GRANT_TTL_MS (ms) \u2014 d\u00F9ng cho test / m\u00F4i tr\u01B0\u1EDDng mu\u1ED1n ng\u1EAFn h\u01A1n.\nconst GRANT_TTL_MS = Number(process.env.FANLUC_GRANT_TTL_MS) > 0 ? Number(process.env.FANLUC_GRANT_TTL_MS) : 5 * 60 * 1000;\nfunction isGranted(type: \"file\" | \"shell\"): boolean {\n return permissionGrants[type] > Date.now();\n}\nfunction grantPermission(type: \"file\" | \"shell\" | \"all\") {\n const until = Date.now() + GRANT_TTL_MS;\n if (type === \"all\" || type === \"file\") permissionGrants.file = until;\n if (type === \"all\" || type === \"shell\") permissionGrants.shell = until;\n}\nfunction clearGrants() {\n permissionGrants = { file: 0, shell: 0 };\n}\n\nlet FIREJAIL_AVAILABLE = false;\nif (!IS_WINDOWS) {\n try {\n execFileSync(\"which\", [\"firejail\"], { stdio: \"ignore\" });\n FIREJAIL_AVAILABLE = true;\n console.log(\"[run_cmd] firejail detected \u2014 sandboxing run_cmd with it.\");\n } catch {\n console.warn(\n \"[run_cmd] firejail not found \u2014 run_cmd will still be jailed to \" +\n WORKSPACE_DIR + \" with a stripped env + blocklist, but for real OS-level \" +\n \"isolation install firejail (`sudo apt-get install -y firejail`) or run \" +\n \"this whole server inside a Docker container.\"\n );\n }\n} else {\n console.log(\"[run_cmd] Windows detected \u2014 firejail disabled, using PowerShell/cmd sandbox (blocklist enforced, permission ask blocks by default)\");\n}\n\nlet ZIP_AVAILABLE = false;\nlet UNZIP_AVAILABLE = false;\nif (!IS_WINDOWS) {\n try {\n execFileSync(\"which\", [\"zip\"], { stdio: \"ignore\" });\n ZIP_AVAILABLE = true;\n } catch {}\n try {\n execFileSync(\"which\", [\"unzip\"], { stdio: \"ignore\" });\n UNZIP_AVAILABLE = true;\n } catch {}\n} else {\n // On Windows, prefer python zipfile fallback; check if powershell Expand-Archive exists\n // We keep false to trigger python fallback unless zip/unzip are on PATH\n try {\n execFileSync(\"where\", [\"zip\"], { stdio: \"ignore\" });\n ZIP_AVAILABLE = true;\n } catch {}\n try {\n execFileSync(\"where\", [\"unzip\"], { stdio: \"ignore\" });\n UNZIP_AVAILABLE = true;\n } catch {}\n}\n\nfunction preprocessCommand(command: string): string {\n let trimmed = command.trim();\n\n // If command calls zip and zip CLI is missing, fallback to python3 zipfile\n if (!ZIP_AVAILABLE && /^zip\\s+/i.test(trimmed)) {\n const parts = trimmed.split(/\\s+/).slice(1);\n if (parts.length >= 2) {\n const zipFile = parts[0];\n const files = parts.slice(1).join(\" \");\n return `python3 -m zipfile -c ${zipFile} ${files}`;\n }\n }\n\n // If command calls unzip and unzip CLI is missing, fallback to python3 zipfile\n if (!UNZIP_AVAILABLE && /^unzip\\s+/i.test(trimmed)) {\n const parts = trimmed.split(/\\s+/).slice(1);\n let zipFile = \"\";\n let outDir = WORKSPACE_DIR;\n for (let i = 0; i < parts.length; i++) {\n if (parts[i] === \"-d\" && parts[i + 1]) {\n outDir = parts[i + 1];\n i++;\n } else if (!zipFile && !parts[i].startsWith(\"-\")) {\n zipFile = parts[i];\n }\n }\n if (zipFile) {\n return `python3 -m zipfile -e ${zipFile} ${outDir}`;\n }\n }\n\n return trimmed;\n}\n\n// Defense-in-depth blocklist: obviously destructive, exfiltrating, or\n// privilege-escalating patterns get rejected outright before spawning\n// anything. Not meant to be a complete sandbox on its own.\n// G\u01102: logic \u0111\u00E3 t\u00E1ch sang src/core/security/blocklist.ts (pure, c\u00F3 test).\n// PowerShell `Remove-Item -Recurse` kh\u00F4ng c\u00F2n b\u1ECB ch\u1EB7n b\u1EEBa: ch\u1EC9 ch\u1EB7n khi \u0111\u00EDch\n// nguy hi\u1EC3m (g\u1ED1c \u1ED5 \u0111\u0129a, ngo\u00E0i workspace, ~, $HOME, wildcard tr\u00F9m h\u1EBFt, ...).\nfunction findBlockedPattern(command: string): string | null {\n return findBlockedCommand(command, { workspaceDir: WORKSPACE_DIR, platform: process.platform });\n}\n\n// ============================================================================\n// Web Search & Fetch helpers\n//\n// Goal: search multiple free, no-API-key engines in parallel (so one engine\n// getting blocked/rate-limited doesn't take the whole tool down), then filter\n// out domains that are known to block scraping / require login / render\n// nothing without JS, and rank the survivors so well-established, reputable\n// sources are offered first. Fetch then extracts the actual article content\n// (via Mozilla's Readability algorithm - the same engine behind Firefox's\n// Reader View) instead of dumping every nav/ads/footer string on the page.\n// ============================================================================\n\nconst DESKTOP_UA =\n \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36\";\n\n// Hosts that are effectively unfetchable as plain HTML: they either require a\n// login, render everything client-side via JS, or actively block scrapers.\n// Kept out of search results entirely, and fast-failed (no network round\n// trip) if the AI tries to fetch() one directly.\nconst BLOCKED_HOST_SUFFIXES = [\n \"facebook.com\",\n \"fb.com\",\n \"instagram.com\",\n \"threads.net\",\n \"twitter.com\",\n \"x.com\",\n \"tiktok.com\",\n \"linkedin.com\",\n \"pinterest.com\",\n \"pinterest.jp\",\n \"quora.com\",\n \"discord.com\",\n \"discord.gg\",\n \"messenger.com\",\n \"whatsapp.com\",\n \"t.me\",\n \"telegram.org\",\n \"youtube.com\",\n \"youtu.be\",\n \"music.youtube.com\",\n \"zalo.me\",\n \"scribd.com\",\n \"academia.edu\",\n \"accounts.google.com\",\n \"myaccount.google.com\",\n];\n\n// Hosts that ARE fetchable, just not at the URL an engine hands back. Rewrite\n// before fetching instead of blocking outright.\nconst DOMAIN_REWRITES: Record<string, string> = {\n \"reddit.com\": \"old.reddit.com\",\n \"www.reddit.com\": \"old.reddit.com\",\n};\n\n// Sources worth ranking higher: encyclopedic/reference, .gov/.edu, major wire\n// services & newsrooms, and well-known Vietnamese outlets (since this tool is\n// used mostly for Vietnamese-language queries). This is a ranking boost, not\n// an allowlist - unknown domains still get through, just lower in the list.\nconst REPUTABLE_HOST_SUFFIXES = [\n \"wikipedia.org\",\n \"github.com\",\n \"stackoverflow.com\",\n \"developer.mozilla.org\",\n \"docs.python.org\",\n \"npmjs.com\",\n \"arxiv.org\",\n \"bbc.com\",\n \"reuters.com\",\n \"apnews.com\",\n \"nytimes.com\",\n \"theguardian.com\",\n \"forbes.com\",\n \"bloomberg.com\",\n \"nature.com\",\n \"sciencedirect.com\",\n \"vnexpress.net\",\n \"tuoitre.vn\",\n \"thanhnien.vn\",\n \"nhandan.vn\",\n \"baochinhphu.vn\",\n \"vietnamnet.vn\",\n \"laodong.vn\",\n \"dantri.com.vn\",\n \"vtv.vn\",\n \"vov.vn\",\n];\nconst REPUTABLE_TLD_SUFFIXES = [\".gov\", \".edu\", \".gov.vn\", \".edu.vn\"];\n\nconst NON_HTML_EXTENSIONS = [\n \".pdf\", \".doc\", \".docx\", \".xls\", \".xlsx\", \".ppt\", \".pptx\",\n \".zip\", \".rar\", \".7z\", \".tar\", \".gz\",\n \".jpg\", \".jpeg\", \".png\", \".gif\", \".webp\", \".svg\", \".bmp\", \".ico\",\n \".mp3\", \".mp4\", \".avi\", \".mov\", \".wav\", \".exe\", \".apk\", \".dmg\",\n];\n\nfunction hostMatchesSuffixList(hostname: string, suffixes: string[]): boolean {\n const h = hostname.toLowerCase().replace(/^www\\./, \"\");\n return suffixes.some((s) => h === s || h.endsWith(\".\" + s));\n}\n\nfunction isBlockedHost(hostname: string): boolean {\n if (!hostname) return false;\n return hostMatchesSuffixList(hostname, BLOCKED_HOST_SUFFIXES);\n}\n\nfunction applyDomainRewrite(urlStr: string): string {\n try {\n const u = new URL(urlStr);\n const host = u.hostname.toLowerCase();\n if (DOMAIN_REWRITES[host]) {\n u.hostname = DOMAIN_REWRITES[host];\n return u.toString();\n }\n return urlStr;\n } catch {\n return urlStr;\n }\n}\n\nfunction reputationScore(hostname: string): number {\n if (!hostname) return 0;\n const h = hostname.toLowerCase();\n if (hostMatchesSuffixList(h, REPUTABLE_HOST_SUFFIXES)) return 10;\n if (REPUTABLE_TLD_SUFFIXES.some((tld) => h.endsWith(tld))) return 8;\n return 0;\n}\n\nfunction looksLikeNonHtmlFile(urlStr: string): boolean {\n try {\n const p = new URL(urlStr).pathname.toLowerCase();\n return NON_HTML_EXTENSIONS.some((ext) => p.endsWith(ext));\n } catch {\n return false;\n }\n}\n\nfunction decodeHtmlEntities(str: string): string {\n if (!str) return \"\";\n return str\n .replace(/ /g, \" \")\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/"/g, \"\\\"\")\n .replace(/�?39;/g, \"'\")\n .replace(/'/g, \"'\")\n .replace(/’|‘/g, \"'\")\n .replace(/”|“/g, \"\\\"\")\n .replace(/—/g, \"\u2014\")\n .replace(/–/g, \"\u2013\")\n .replace(/…/g, \"\u2026\")\n .replace(/&#x([0-9a-fA-F]+);/g, (_, hex) => String.fromCodePoint(parseInt(hex, 16)))\n .replace(/&#(\\d+);/g, (_, dec) => String.fromCodePoint(parseInt(dec, 10)));\n}\n\nfunction stripInnerTags(str: string): string {\n if (!str) return \"\";\n return str.replace(/<[^>]+>/g, \" \").replace(/\\s+/g, \" \").trim();\n}\n\ninterface RawSearchResult {\n url: string;\n title: string;\n snippet: string;\n engine: string;\n}\n\n// --- Engine 1: DuckDuckGo HTML (no JS, no API key, generally the most\n// scrape-tolerant of the major engines) ---\nasync function searchDuckDuckGo(query: string, count: number): Promise<RawSearchResult[]> {\n const results: RawSearchResult[] = [];\n try {\n const q = encodeURIComponent(query.trim());\n const resp = await fetch(`https://html.duckduckgo.com/html/?q=${q}&kl=wt-wt`, {\n headers: {\n \"User-Agent\": DESKTOP_UA,\n \"Accept-Language\": \"en-US,en;q=0.9,vi;q=0.8\",\n },\n });\n if (!resp.ok) return results;\n const html = await resp.text();\n const resultRegex = /<a[^>]+class=\"result__a\"[^>]+href=\"([^\"]+)\"[^>]*>([\\s\\S]*?)<\\/a>[\\s\\S]*?<a[^>]+class=\"result__snippet\"[^>]*>([\\s\\S]*?)<\\/a>/gi;\n let m: RegExpExecArray | null;\n while ((m = resultRegex.exec(html)) !== null && results.length < count * 2) {\n let url = m[1];\n if (url.startsWith(\"//duckduckgo.com/l/\")) {\n const uddgMatch = url.match(/[?&]uddg=([^&]+)/);\n if (uddgMatch) url = decodeURIComponent(uddgMatch[1]);\n } else if (url.startsWith(\"//\")) {\n url = \"https:\" + url;\n }\n if (!url.startsWith(\"http\")) continue;\n const title = decodeHtmlEntities(stripInnerTags(m[2]));\n const snippet = decodeHtmlEntities(stripInnerTags(m[3])) || title;\n if (!title && !snippet) continue;\n results.push({ url, title, snippet, engine: \"duckduckgo\" });\n }\n } catch (err) {\n console.warn(\"DuckDuckGo search error:\", err);\n }\n return results;\n}\n\n// --- Engine 2: Bing HTML (organic results render with real hrefs in the\n// no-JS markup) ---\nasync function searchBing(query: string, count: number): Promise<RawSearchResult[]> {\n const results: RawSearchResult[] = [];\n try {\n const q = encodeURIComponent(query.trim());\n const resp = await fetch(`https://www.bing.com/search?q=${q}&count=${Math.min(30, count * 3)}&setlang=en-US`, {\n headers: {\n \"User-Agent\": DESKTOP_UA,\n \"Accept-Language\": \"en-US,en;q=0.9,vi;q=0.8\",\n },\n });\n if (!resp.ok) return results;\n const html = await resp.text();\n const resultRegex = /<li class=\"b_algo\"[^>]*>[\\s\\S]*?<h2>[\\s\\S]*?<a href=\"([^\"]+)\"[^>]*>([\\s\\S]*?)<\\/a>[\\s\\S]*?<\\/h2>([\\s\\S]*?)<\\/li>/gi;\n let m: RegExpExecArray | null;\n while ((m = resultRegex.exec(html)) !== null && results.length < count * 2) {\n const url = m[1];\n if (!url.startsWith(\"http\")) continue;\n const title = decodeHtmlEntities(stripInnerTags(m[2]));\n const bodyBlock = m[3] || \"\";\n const snippetMatch =\n bodyBlock.match(/<p[^>]*>([\\s\\S]*?)<\\/p>/i) ||\n bodyBlock.match(/<div class=\"b_caption\"[^>]*>([\\s\\S]*?)<\\/div>/i);\n const snippet = snippetMatch ? decodeHtmlEntities(stripInnerTags(snippetMatch[1])) : title;\n if (!title && !snippet) continue;\n results.push({ url, title, snippet, engine: \"bing\" });\n }\n } catch (err) {\n console.warn(\"Bing search error:\", err);\n }\n return results;\n}\n\n// --- Engine 3: Yahoo Japan search (kept from the original implementation as\n// a third, independent fallback source) ---\nasync function searchYahooJP(query: string, count: number): Promise<RawSearchResult[]> {\n const results: RawSearchResult[] = [];\n const q = encodeURIComponent(query.trim());\n\n try {\n const response = await fetch(`https://search.yahoo.co.jp/search?p=${q}`, {\n headers: {\n \"User-Agent\": DESKTOP_UA,\n \"Accept-Language\": \"en-US,en;q=0.9,vi;q=0.8\",\n },\n });\n\n if (response.ok) {\n const html = await response.text();\n const sectionRegex = /<div class=\"sw-Card[^\"]*\"[\\s\\S]*?<a\\s+href=\"([^\"]+)\"[^>]*>[\\s\\S]*?<h3[^>]*>([\\s\\S]*?)<\\/h3>[\\s\\S]*?(?:<p class=\"sw-Card__summary\">([\\s\\S]*?)<\\/p>)?/gi;\n let match: RegExpExecArray | null;\n while ((match = sectionRegex.exec(html)) !== null && results.length < count) {\n const url = match[1];\n if (url.startsWith(\"http\") && !url.includes(\"search.yahoo.co.jp\")) {\n const title = decodeHtmlEntities(stripInnerTags(match[2]));\n const snippet = match[3] ? decodeHtmlEntities(stripInnerTags(match[3])) : title;\n results.push({ url, title, snippet, engine: \"yahoo\" });\n }\n }\n }\n } catch (err) {\n console.warn(\"Yahoo search primary endpoint error:\", err);\n }\n\n if (results.length === 0) {\n try {\n const newsRes = await fetch(`https://news.search.yahoo.com/search?p=${q}`, {\n headers: { \"User-Agent\": DESKTOP_UA },\n });\n if (newsRes.ok) {\n const newsHtml = await newsRes.text();\n const newsRegex = /<h4[^>]*><a[^>]+href=\"([^\"]+)\"[^>]*>(.*?)<\\/a><\\/h4>/gi;\n let nMatch: RegExpExecArray | null;\n while ((nMatch = newsRegex.exec(newsHtml)) !== null && results.length < count) {\n let link = nMatch[1];\n if (link.includes(\"/RU=\")) {\n const ruMatch = link.match(/\\/RU=([^/]+)/);\n if (ruMatch) link = decodeURIComponent(ruMatch[1]);\n }\n const title = decodeHtmlEntities(stripInnerTags(nMatch[2]));\n if (link.startsWith(\"http\")) {\n results.push({ url: link, title, snippet: title, engine: \"yahoo-news\" });\n }\n }\n }\n } catch (err) {\n console.warn(\"Yahoo news fallback error:\", err);\n }\n }\n\n return results;\n}\n\nfunction interleaveResults(arrays: RawSearchResult[][]): RawSearchResult[] {\n const out: RawSearchResult[] = [];\n const maxLen = Math.max(0, ...arrays.map((a) => a.length));\n for (let i = 0; i < maxLen; i++) {\n for (const arr of arrays) {\n if (arr[i]) out.push(arr[i]);\n }\n }\n return out;\n}\n\nfunction normalizeForDedupe(url: string): string {\n try {\n const u = new URL(url);\n return (u.hostname.replace(/^www\\./, \"\") + u.pathname.replace(/\\/$/, \"\")).toLowerCase();\n } catch {\n return url.toLowerCase();\n }\n}\n\n// Filters out unfetchable/blocked/non-HTML results, de-duplicates, caps how\n// many results a single domain can contribute (keeps sources diverse), and\n// sorts reputable domains first.\nfunction mergeAndFilterResults(all: RawSearchResult[], count: number): { url: string; snippet: string }[] {\n const seen = new Set<string>();\n const perDomainCount = new Map<string, number>();\n const filtered: (RawSearchResult & { score: number })[] = [];\n\n for (const r of all) {\n if (!r.url || !r.url.startsWith(\"http\")) continue;\n let hostname = \"\";\n try {\n hostname = new URL(r.url).hostname.toLowerCase();\n } catch {\n continue;\n }\n if (isBlockedHost(hostname)) continue;\n if (looksLikeNonHtmlFile(r.url)) continue;\n\n const dedupeKey = normalizeForDedupe(r.url);\n if (seen.has(dedupeKey)) continue;\n\n const domainKey = hostname.replace(/^www\\./, \"\");\n const domainCount = perDomainCount.get(domainKey) || 0;\n if (domainCount >= 2) continue;\n\n seen.add(dedupeKey);\n perDomainCount.set(domainKey, domainCount + 1);\n filtered.push({ ...r, url: applyDomainRewrite(r.url), score: reputationScore(hostname) });\n }\n\n filtered.sort((a, b) => b.score - a.score);\n\n return filtered.slice(0, count).map((r) => ({\n url: r.url,\n snippet: (r.snippet && r.snippet.trim()) || r.title || r.url,\n }));\n}\n\n// --- Fetch-with-byte-cap: reads the response body incrementally and stops\n// once MAX_FETCH_BYTES is hit, instead of buffering an unbounded page ---\nconst MAX_FETCH_BYTES = 6 * 1024 * 1024; // 6MB safety cap\n\nasync function fetchWithByteLimit(\n url: string,\n signal: AbortSignal,\n maxBytes: number\n): Promise<{ ok: boolean; status: number; contentType: string; body: string }> {\n const response = await fetch(url, {\n signal,\n redirect: \"follow\",\n headers: {\n \"User-Agent\": DESKTOP_UA,\n \"Accept\": \"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\",\n \"Accept-Language\": \"vi-VN,vi;q=0.9,en-US;q=0.8,en;q=0.7\",\n },\n });\n\n const contentType = response.headers.get(\"content-type\") || \"\";\n\n if (!response.body) {\n const text = await response.text();\n return { ok: response.ok, status: response.status, contentType, body: text.slice(0, maxBytes) };\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let received = 0;\n let body = \"\";\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n received += value.byteLength;\n body += decoder.decode(value, { stream: true });\n if (received >= maxBytes) {\n try {\n await reader.cancel();\n } catch {\n // ignore\n }\n break;\n }\n }\n body += decoder.decode();\n return { ok: response.ok, status: response.status, contentType, body };\n}\n\nfunction fallbackCleanHtml(html: string): string {\n const stripped = html\n .replace(/<script[\\s\\S]*?<\\/script>/gi, \" \")\n .replace(/<style[\\s\\S]*?<\\/style>/gi, \" \")\n .replace(/<noscript[\\s\\S]*?<\\/noscript>/gi, \" \")\n .replace(/<svg[\\s\\S]*?<\\/svg>/gi, \" \")\n .replace(/<iframe[\\s\\S]*?<\\/iframe>/gi, \" \")\n .replace(/<!--[\\s\\S]*?-->/g, \" \")\n .replace(/<(nav|header|footer|aside|form|button|select|figure|figcaption)[^>]*>[\\s\\S]*?<\\/\\1>/gi, \" \")\n .replace(/<[^>]+>/g, \" \")\n .replace(/\\s+/g, \" \")\n .trim();\n return decodeHtmlEntities(stripped);\n}\n\n// Extracts the actual article content from a raw HTML page. Tries Mozilla's\n// Readability algorithm first (the same one behind Firefox Reader View -\n// strips nav/ads/footers/comments and keeps just the article body); falls\n// back to tag-stripping (still boilerplate-tag-aware) if Readability can't\n// find an article on the page (e.g. it's a listing/home page, not an article).\nfunction extractReadableContent(\n html: string,\n url: string\n): { title: string; text: string; usedReadability: boolean } {\n try {\n const dom = new JSDOM(html, { url });\n const doc = dom.window.document;\n doc.querySelectorAll(\"script, style, noscript, iframe, svg, form\").forEach((el) => el.remove());\n\n const reader = new Readability(doc, { charThreshold: 200 });\n const article = reader.parse();\n\n if (article && article.textContent && article.textContent.trim().length > 150) {\n const cleanText = article.textContent.replace(/[ \\t]+/g, \" \").replace(/\\n{3,}/g, \"\\n\\n\").trim();\n return { title: article.title || \"\", text: cleanText, usedReadability: true };\n }\n } catch (err: any) {\n console.warn(\"Readability extraction failed, falling back:\", err?.message);\n }\n\n return { title: \"\", text: fallbackCleanHtml(html), usedReadability: false };\n}\n\n\n// ============================================================================\n// SearXNG \u2014 default search engine, Yahoo JP fallback\n// Config: SEARXNG_URL (or SEARXNG) env var, defaults to http://localhost:8080\n// Needs settings.yml: search.formats: [html, json] and server.limiter: false\n// Test: curl \"http://localhost:8080/search?q=test&format=json\"\n// ============================================================================\n// Opt-in: empty = disabled (no wasted request to a SearXNG that is not running).\nconst SEARXNG_URL = (process.env.SEARXNG_URL || process.env.SEARXNG || \"\").replace(/\\/$/, \"\");\n\nasync function searchSearXNG(query: string, count: number, categories: \"general\" | \"images\" = \"general\", baseUrl: string = SEARXNG_URL): Promise<RawSearchResult[]> {\n const results: RawSearchResult[] = [];\n if (!baseUrl) return results;\n try {\n const params = new URLSearchParams({ q: query.trim(), format: \"json\", categories, pageno: \"1\" });\n const url = `${baseUrl}/search?${params.toString()}`;\n const resp = await fetch(url, {\n signal: AbortSignal.timeout(6000),\n headers: {\n \"User-Agent\": DESKTOP_UA,\n \"Accept\": \"application/json\",\n \"Accept-Language\": \"en-US,en;q=0.9,vi;q=0.8\",\n },\n });\n if (!resp.ok) {\n console.warn(`SearXNG search failed ${resp.status} for \"${query}\"`);\n return results;\n }\n const j: any = await resp.json();\n const raw = Array.isArray(j.results) ? j.results : [];\n for (const x of raw) {\n if (results.length >= count * 2) break;\n if (categories === \"images\") {\n const title = (x.title || x.content || \"\").toString();\n const url = (x.url || x.img_src || \"\").toString();\n const img_src = (x.img_src || x.url || \"\").toString();\n const thumb = (x.thumbnail_src || x.img_src || x.thumbnail || \"\").toString();\n if (!img_src && !url) continue;\n results.push({\n url: url || img_src,\n title,\n snippet: title,\n engine: \"searxng-images\",\n _img_src: img_src,\n _thumb: thumb,\n } as any);\n } else {\n const title = (x.title || \"\").toString();\n const url = (x.url || \"\").toString();\n const snippet = (x.content || x.title || \"\").toString();\n if (!url || !url.startsWith(\"http\")) continue;\n results.push({ url, title, snippet, engine: \"searxng\" });\n }\n }\n } catch (err) {\n console.warn(\"SearXNG search error:\", err);\n }\n return results;\n}\n\n\n// ---- User-supplied URLs (from browser settings): must be public http(s) ----\nfunction isPrivateIp(ip: string): boolean {\n const v = ip.toLowerCase();\n if (v.startsWith(\"::ffff:\")) return isPrivateIp(v.slice(7));\n if (net.isIPv4(v)) {\n const [a, b] = v.split(\".\").map(Number);\n return a === 0 || a === 10 || a === 127 || (a === 169 && b === 254) || (a === 172 && b >= 16 && b <= 31) || (a === 192 && b === 168) || (a === 100 && b >= 64 && b <= 127);\n }\n return v === \"::1\" || v === \"::\" || v.startsWith(\"fc\") || v.startsWith(\"fd\") || v.startsWith(\"fe80\");\n}\nasync function assertPublicUrl(raw: string): Promise<URL> {\n const u = new URL(raw);\n if (u.protocol !== \"http:\" && u.protocol !== \"https:\") throw new Error(\"Only http/https URLs are allowed\");\n if (process.env.ALLOW_PRIVATE_URLS === \"1\") return u;\n const host = u.hostname.replace(/^\\[|\\]$/g, \"\");\n if (host === \"localhost\" || host.endsWith(\".local\") || host.endsWith(\".internal\")) throw new Error(\"Private/local hosts are not allowed\");\n const addrs = net.isIP(host) ? [{ address: host }] : await dns.lookup(host, { all: true });\n for (const a of addrs) if (isPrivateIp(a.address)) throw new Error(\"Private/local hosts are not allowed\");\n return u;\n}\nasync function resolveSearxUrl(req: any): Promise<string> {\n const raw = String(req.body?.searxngUrl || req.headers[\"x-searxng-url\"] || \"\").trim();\n if (!raw) return SEARXNG_URL;\n try {\n const u = await assertPublicUrl(raw);\n return (u.origin + u.pathname).replace(/\\/$/, \"\");\n } catch (e: any) {\n console.warn(\"[SearXNG] user URL rejected:\", e?.message);\n return SEARXNG_URL;\n }\n}\n\nasync function searchSearXNGGeneral(query: string, count: number): Promise<RawSearchResult[]> {\n return searchSearXNG(query, count, \"general\");\n}\n\n// ============================================================================\n// Image search helpers (SearXNG categories=images) + image proxy\n// ============================================================================\ninterface ImageResult {\n title: string;\n src: string;\n thumb: string;\n page: string;\n}\n\n// ============================================================================\n// MCP \u2014 file-based config (mcp.json), server.ts as bridge\n// Format: Claude Code style { \"mcpServers\": { name: {type, command, args, url, headers, env, enabled} } }\n// Also supports opencode style { \"mcp\": { ... } } / { \"mcp\": { \"servers\": { ... } } }\n// Web can't spawn processes, so server.ts bridges via MCP SDK\n// Security: only read config from file on server; never accept command/url from client\n// ============================================================================\nfunction stripJsonc(s: string): string {\n // Remove // and /* */ comments but keep them inside strings (e.g. \"https://...\")\n return s.replace(/(\"(?:\\\\.|[^\"\\\\])*\")|\\/\\/.*$|\\/\\*[\\s\\S]*?\\*\\//gm, (_m, str) => str ?? \"\");\n}\nfunction isLocalRequest(req: any): boolean {\n const ip = String(req.socket?.remoteAddress || \"\");\n const loop = ip === \"127.0.0.1\" || ip === \"::1\" || ip === \"::ffff:127.0.0.1\";\n return loop && !req.headers[\"x-forwarded-for\"]; // tunnels (ngrok) add x-forwarded-for\n}\nfunction mcpAdminGuard(req: any, res: any, next: any) {\n const token = process.env.ADMIN_TOKEN;\n if (!token) return next(); // no ADMIN_TOKEN set = open (personal instance), same as before\n if (req.headers[\"x-admin-token\"] === token) return next();\n return res.status(403).json({ error: \"Admin only: send header x-admin-token matching ADMIN_TOKEN.\" });\n}\nfunction resolveEnvVars(str: string): string {\n if (typeof str !== \"string\") return str;\n return str.replace(/\\$\\{([^}]+)\\}/g, (_, name) => process.env[name.trim()] ?? \"\");\n}\nfunction resolveEnvObject(obj: Record<string, string> | undefined): Record<string, string> | undefined {\n if (!obj || typeof obj !== \"object\") return obj;\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(obj)) {\n out[k] = typeof v === \"string\" ? resolveEnvVars(v) : v;\n }\n return out;\n}\n\ntype McpEntry = {\n client: Client | null;\n tools: any[];\n status: \"connected\" | \"failed\" | \"disabled\" | \"connecting\";\n error?: string;\n config: any;\n type: string;\n};\n\nconst mcp = new Map<string, McpEntry>();\n\nfunction normalizeMcpType(t: string): \"stdio\" | \"http\" {\n const low = (t || \"\").toLowerCase();\n if (low === \"http\" || low === \"remote\" || low === \"streamablehttp\" || low === \"sse\") return \"http\";\n return \"stdio\";\n}\n\nasync function connectMcp(name: string, cfg: any) {\n const explicitlyDisabled = cfg.enabled === false || cfg.disabled === true;\n if (explicitlyDisabled) {\n mcp.set(name, { client: null, tools: [], status: \"disabled\", config: cfg, type: normalizeMcpType(cfg.type) });\n return;\n }\n const type = normalizeMcpType(cfg.type || (cfg.url ? \"http\" : \"stdio\"));\n const entry: McpEntry = { client: null, tools: [], status: \"connecting\", config: cfg, type };\n mcp.set(name, entry);\n try {\n let transport: any;\n if (type === \"http\") {\n const rawUrl = cfg.url;\n if (!rawUrl) throw new Error(\"Missing url for http/remote MCP server\");\n const resolvedUrl = resolveEnvVars(String(rawUrl));\n const headers = resolveEnvObject(cfg.headers) || {};\n transport = new StreamableHTTPClientTransport(new URL(resolvedUrl), { requestInit: { headers } } as any);\n } else {\n let command: string | undefined = cfg.command;\n let args: string[] = Array.isArray(cfg.args) ? cfg.args : [];\n let env: Record<string, string> | undefined = resolveEnvObject(cfg.env || cfg.environment);\n if (Array.isArray(command)) {\n args = (command as string[]).slice(1);\n command = (command as string[])[0];\n }\n if (!command) throw new Error(\"Missing command for stdio/local MCP server\");\n const resolvedCommand = resolveEnvVars(String(command));\n const resolvedArgs = args.map((a) => resolveEnvVars(String(a)));\n transport = new StdioClientTransport({ command: resolvedCommand, args: resolvedArgs, env: env as any } as any);\n }\n const client = new Client({ name: \"fanluc\", version: \"1.0.0\" } as any, { capabilities: {} } as any);\n await client.connect(transport);\n const toolsRes: any = await client.listTools();\n const tools = Array.isArray(toolsRes?.tools) ? toolsRes.tools : [];\n const truncated = tools.map((t: any) => ({\n ...t,\n description: typeof t.description === \"string\" ? t.description : t.description,\n }));\n mcp.set(name, { client, tools: truncated, status: \"connected\", config: cfg, type });\n console.log(`[MCP] ${name} connected \u2014 ${truncated.length} tools`);\n } catch (e: any) {\n const msg = e?.message || String(e);\n console.warn(`[MCP] ${name} failed:`, msg);\n mcp.set(name, { client: null as any, tools: [], status: \"failed\", error: msg, config: cfg, type });\n }\n}\n\nfunction getFanlucConfigDir(): string {\n // Same logic as src/cli/config.ts \u2014 keep in sync\n if (process.env.FANLUC_CONFIG_DIR?.trim()) return process.env.FANLUC_CONFIG_DIR.trim();\n if (IS_WINDOWS) {\n const appData = process.env.APPDATA;\n if (appData) return path.join(appData, \"fanluc\");\n return path.join(os.homedir(), \"AppData\", \"Roaming\", \"fanluc\");\n }\n const xdg = process.env.XDG_CONFIG_HOME;\n if (xdg) return path.join(xdg, \"fanluc\");\n return path.join(os.homedir(), \".config\", \"fanluc\");\n}\n\n\n/** mcp.json lives in the fanluc config dir (never in the user's project directory). */\nfunction mcpConfigPath(): string {\n const dir = getFanlucConfigDir();\n try { fs.mkdirSync(dir, { recursive: true }); } catch {}\n return path.join(dir, \"mcp.json\");\n}\nfunction readMcpServersFile(mcpPath: string): Record<string, any> {\n if (!fs.existsSync(mcpPath)) return {};\n const raw = fs.readFileSync(mcpPath, \"utf-8\").replace(/^\\uFEFF/, \"\");\n if (!raw.trim()) return {};\n const j = JSON.parse(stripJsonc(raw));\n if (j.mcpServers) return j.mcpServers;\n if (j.mcp && j.mcp.servers) return j.mcp.servers;\n if (j.mcp && typeof j.mcp === \"object\") return j.mcp;\n return j;\n}\n\nfunction loadMcpConfigSync(): Record<string, any> {\n const configDir = getFanlucConfigDir();\n // G\u01101-fix4: ch\u1EC9 \u0111\u1ECDc t\u1EEB config dir, kh\u00F4ng t\u1EF1 n\u1EA1p cwd/mcp.json\n const candidates = [\n path.join(configDir, \"mcp.json\"),\n path.join(configDir, \"mcp.jsonc\"),\n ];\n for (const p of candidates) {\n try {\n if (fs.existsSync(p)) {\n const raw = fs.readFileSync(p, \"utf-8\").replace(/^\\uFEFF/, \"\");\n const cleaned = stripJsonc(raw);\n const j = JSON.parse(cleaned);\n if (j.mcpServers && typeof j.mcpServers === \"object\") return j.mcpServers;\n if (j.mcp && j.mcp.servers && typeof j.mcp.servers === \"object\") return j.mcp.servers;\n if (j.mcp && typeof j.mcp === \"object\" && !j.mcp.servers) {\n const maybe = j.mcp;\n const vals = Object.values(maybe) as any[];\n if (vals.length && vals.every((v: any) => v && typeof v.type === \"string\")) return maybe;\n }\n const topVals = Object.values(j) as any[];\n if (topVals.length && topVals.every((v: any) => v && typeof v.type === \"string\")) return j;\n return {};\n }\n } catch (e) {\n console.warn(`Failed to load MCP config from ${p}:`, e);\n }\n }\n return {};\n}\n\nasync function initMcpFromFile() {\n const cfgMap = loadMcpConfigSync();\n const entries = Object.entries(cfgMap);\n if (entries.length === 0) {\n console.log(\"[MCP] no mcp.json found or empty \u2014 skipping MCP init\");\n return;\n }\n console.log(`[MCP] loading ${entries.length} server(s) from mcp.json`);\n for (const [name, cfg] of entries) {\n await connectMcp(name, cfg);\n }\n}\n\nfunction getMcpToolsForModel(): any[] {\n const out: any[] = [];\n for (const [server, entry] of mcp.entries()) {\n if (entry.status !== \"connected\") continue;\n for (const t of entry.tools) {\n out.push({\n server,\n name: `${server}_${t.name}`,\n originalName: t.name,\n description: t.description || \"\",\n inputSchema: t.inputSchema,\n });\n }\n }\n return out;\n}\n\n\nasync function startServer() {\n const app = express();\n\n // When bound to loopback only, refuse requests whose Host header is not local (blocks DNS-rebinding from web pages).\n {\n const bind = process.env.HOST || \"0.0.0.0\";\n if (bind === \"127.0.0.1\" || bind === \"localhost\" || bind === \"::1\") {\n app.use((req, res, next) => {\n const h = String(req.headers.host || \"\").replace(/:\\d+$/, \"\").replace(/^\\[|\\]$/g, \"\");\n if (h === \"localhost\" || h === \"127.0.0.1\" || h === \"::1\") return next();\n return res.status(403).json({ error: \"Forbidden host\" });\n });\n }\n }\n const PORT = Number(process.env.PORT) || 3000;\n\n app.use(express.json({ limit: \"50mb\" }));\n\n // Init MCP servers from mcp.json (non-blocking, log errors)\n initMcpFromFile().catch((e) => console.warn(\"[MCP] init failed:\", e));\n\n // API Proxy endpoint to solve CORS issues with ngrok / custom REST APIs (Google Colab, Kaggle, Local)\n app.post(\"/api/proxy-chat\", async (req, res) => {\n try {\n const { apiUrl, apiKey, body, customHeaders } = req.body;\n\n if (!apiUrl) {\n return res.status(400).json({ error: \"Missing apiUrl parameter\" });\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"ngrok-skip-browser-warning\": \"true\",\n \"User-Agent\": \"AI-Studio-Rest-Client/1.0\",\n \"Authorization\": `Bearer ${apiKey || \"\"}`,\n ...(customHeaders || {}),\n };\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 300000); // 300 second (5 min) timeout\n\n const response = await fetch(apiUrl, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const responseText = await response.text();\n return res.status(response.status).send(responseText);\n }\n\n if (body?.stream && response.body) {\n res.setHeader(\"Content-Type\", \"text/event-stream\");\n res.setHeader(\"Cache-Control\", \"no-cache\");\n res.setHeader(\"Connection\", \"keep-alive\");\n\n const reader = response.body.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n res.write(Buffer.from(value));\n }\n } catch (streamErr) {\n console.warn(\"Proxy stream pipe interrupted:\", streamErr);\n } finally {\n res.end();\n }\n return;\n }\n\n const responseText = await response.text();\n try {\n const data = JSON.parse(responseText);\n return res.json(data);\n } catch {\n return res.send(responseText);\n }\n } catch (error: any) {\n console.error(\"Proxy error:\", error);\n if (error?.name === \"AbortError\") {\n return res.status(504).json({\n error: \"API response timed out (>5 min) or instance disconnected.\",\n });\n }\n return res.status(500).json({ error: error?.message || \"Internal Proxy Error\" });\n }\n });\n\n // Web Search endpoint (SearXNG primary, multi-engine fallback)\n // SearXNG self-hosted is primary (free, no limits, supports images/news).\n // Yahoo JP kept as fallback. Route kept as /api/yahoo-search for frontend compat.\n app.post(\"/api/yahoo-search\", async (req, res) => {\n try {\n const { query, count = 7 } = req.body;\n if (!query || typeof query !== \"string\") {\n return res.status(400).json({ error: \"Missing query parameter\" });\n }\n\n const maxCount = Math.min(15, Math.max(1, parseInt(count) || 7));\n\n // 1) Try SearXNG first (default)\n let searxResults: RawSearchResult[] = [];\n try {\n searxResults = await searchSearXNG(query, maxCount, \"general\", await resolveSearxUrl(req));\n } catch (e) {\n console.warn(\"SearXNG general search error, falling back:\", e);\n }\n\n if (searxResults.length > 0) {\n // Filter + rank SearXNG results through same pipeline for quality\n let results = mergeAndFilterResults(searxResults, maxCount);\n if (results.length === 0) {\n // If filtering removed everything, use raw\n results = searxResults.slice(0, maxCount).map((r) => ({ url: r.url, snippet: r.snippet || r.title || r.url }));\n }\n const formattedText = `${results.length} results:\\n` + results.map((r) => `${r.url}: ${r.snippet}`).join(\"\\n\");\n return res.json({ count: results.length, results, formattedText, engine: \"searxng\" });\n }\n\n // 2) Fallback to multi-engine (DuckDuckGo + Bing + Yahoo JP)\n const perEngineCount = Math.min(20, maxCount + 6);\n const withTimeout = <T,>(p: Promise<T[]>, ms = 8000): Promise<T[]> =>\n Promise.race([p.catch(() => [] as T[]), new Promise<T[]>((r) => setTimeout(() => r([]), ms))]);\n const [ddgResults, bingResults, yahooResults] = await Promise.all([\n withTimeout(searchDuckDuckGo(query, perEngineCount)),\n withTimeout(searchBing(query, perEngineCount)),\n withTimeout(searchYahooJP(query, perEngineCount)),\n ]);\n\n let results = mergeAndFilterResults(\n interleaveResults([ddgResults, bingResults, yahooResults]),\n maxCount\n );\n\n if (results.length === 0) {\n const rawAll = [...ddgResults, ...bingResults, ...yahooResults];\n results = rawAll.slice(0, maxCount).map((r) => ({ url: r.url, snippet: r.snippet || r.title || r.url }));\n }\n\n const formattedText =\n results.length > 0\n ? `${results.length} results:\\n` + results.map((r) => `${r.url}: ${r.snippet}`).join(\"\\n\")\n : `0 results:\\n(no results found for \"${query}\")`;\n\n return res.json({\n count: results.length,\n results,\n formattedText,\n engine: results.length ? \"fallback\" : \"none\",\n });\n } catch (error: any) {\n console.error(\"Web search error:\", error);\n return res.status(500).json({ error: error?.message || \"Web search failed\" });\n }\n });\n\n // Dedicated SearXNG search (optional direct access)\n app.post(\"/api/searxng-search\", async (req, res) => {\n try {\n const { query, count = 7, categories = \"general\" } = req.body;\n if (!query || typeof query !== \"string\") return res.status(400).json({ error: \"Missing query\" });\n const maxCount = Math.min(15, Math.max(1, parseInt(count) || 7));\n const cat = categories === \"images\" ? \"images\" : \"general\";\n const raw = await searchSearXNG(query, maxCount, cat as any, await resolveSearxUrl(req));\n let results: any[] = [];\n if (cat === \"images\") {\n // Return image-mapped results\n const filtered = raw.slice(0, maxCount).map((r: any) => ({\n title: r.title,\n src: (r as any)._img_src || r.url,\n thumb: (r as any)._thumb || (r as any)._img_src || r.url,\n page: r.url,\n url: r.url,\n }));\n return res.json({ count: filtered.length, results: filtered, formattedText: filtered.length ? `${filtered.length} images:${filtered.map((x:any)=>\" \"+x.src).join(\",\")}` : \"0 images\" });\n } else {\n results = mergeAndFilterResults(raw, maxCount);\n if (results.length === 0) results = raw.slice(0, maxCount).map((r) => ({ url: r.url, snippet: r.snippet }));\n const formattedText = results.length ? `${results.length} results:\\n` + results.map((r:any)=>`${r.url}: ${r.snippet}`).join(\"\\n\") : `0 results\\n(no results)`;\n return res.json({ count: results.length, results, formattedText });\n }\n } catch (e:any){ return res.status(500).json({error:e?.message});}\n });\n\n // Image search (SearXNG categories=images, fallback to empty)\n app.post(\"/api/image-search\", async (req, res) => {\n try {\n const { query, count = 6 } = req.body;\n if (!query || typeof query !== \"string\") return res.status(400).json({ error: \"Missing query\" });\n const maxCount = Math.min(12, Math.max(1, parseInt(count) || 6));\n const raw = await searchSearXNG(query, maxCount, \"images\", await resolveSearxUrl(req));\n // Map to UI-friendly shape\n let images: ImageResult[] = raw.slice(0, maxCount).map((r: any) => ({\n title: r.title || query,\n src: (r as any)._img_src || r.url,\n thumb: (r as any)._thumb || (r as any)._img_src || r.url,\n page: r.url,\n })).filter((x) => x.src && x.src.startsWith(\"http\"));\n // Dedupe by src\n const seen = new Set<string>();\n images = images.filter((x) => { if(seen.has(x.src)) return false; seen.add(x.src); return true; });\n const formattedText = images.length ? `\u0110\u00E3 hi\u1EC3n th\u1ECB ${images.length} \u1EA3nh v\u1EC1 \"${query}\"` : `Kh\u00F4ng t\u00ECm th\u1EA5y \u1EA3nh cho \"${query}\"`;\n return res.json({ count: images.length, images, formattedText });\n } catch (e:any){\n console.error(\"Image search error:\", e);\n return res.status(500).json({ error: e?.message || \"Image search failed\" });\n }\n });\n\n // Image proxy (to avoid hotlink blocking)\n app.get(\"/api/image-proxy\", async (req, res) => {\n try {\n const url = String(req.query.url || \"\");\n if (!url || !url.startsWith(\"http\")) return res.status(400).send(\"Missing url\");\n const parsed = new URL(url);\n if (isBlockedHost(parsed.hostname)) return res.status(403).send(\"Blocked host\");\n let resp: Response | null = null;\n let cur = url;\n for (let hop = 0; hop < 4; hop++) {\n const h = new URL(cur).hostname;\n if (isBlockedHost(h)) return res.status(403).send(\"Blocked host\");\n resp = await fetch(cur, { redirect: \"manual\", headers: { \"User-Agent\": DESKTOP_UA, \"Accept\": \"image/*,*/*\" } } as any);\n const loc = resp.headers.get(\"location\");\n if (resp.status >= 300 && resp.status < 400 && loc) { cur = new URL(loc, cur).toString(); resp = null; continue; }\n break;\n }\n if (!resp) return res.status(508).send(\"Too many redirects\");\n if (!resp.ok) return res.status(resp.status).send(\"Fetch failed\");\n const ct = resp.headers.get(\"content-type\") || \"image/jpeg\";\n if (!ct.startsWith(\"image/\")) return res.status(415).send(\"Not an image\");\n res.setHeader(\"Content-Type\", ct);\n res.setHeader(\"Cache-Control\", \"public, max-age=86400\");\n if (resp.body) {\n const reader = resp.body.getReader();\n // stream\n res.flushHeaders?.();\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n res.write(Buffer.from(value));\n }\n res.end();\n } else {\n const buf = Buffer.from(await resp.arrayBuffer());\n res.send(buf);\n }\n } catch (e:any){ return res.status(500).send(e?.message); }\n });\n\n // ==========================================================================\n // MCP endpoints\n // Security: config only from file; client never sends command/url\n // ==========================================================================\n app.get(\"/api/mcp/status\", (_req, res) => {\n const list = [...mcp.entries()].map(([name, v]) => ({\n name,\n type: v.type, // stdio / http\n status: v.status, // connected / failed / disabled / connecting\n tools: v.tools,\n toolCount: v.tools.length,\n error: v.error || null,\n }));\n // Also include tools for model (prefixed)\n const modelTools = getMcpToolsForModel();\n res.json({ servers: list, modelTools, count: list.length });\n });\n\n app.get(\"/api/mcp/tools\", (_req, res) => {\n // For model injection: only enabled connected servers, truncated\n res.json({ tools: getMcpToolsForModel() });\n });\n\n app.post(\"/api/mcp/call\", async (req, res) => {\n try {\n const { server, tool, args, arguments: altArgs } = req.body || {};\n const toolName = tool;\n const toolArgs = args ?? altArgs ?? {};\n if (!server || !toolName) return res.status(400).json({ error: \"Missing server or tool\" });\n const entry = mcp.get(server);\n if (!entry) return res.status(404).json({ error: `MCP server \"${server}\" not found` });\n if (entry.status !== \"connected\" || !entry.client) return res.status(400).json({ error: `MCP server \"${server}\" not connected (${entry.status})${entry.error ? \": \"+entry.error : \"\"}` });\n // Validate tool exists on this server (or with prefix)\n const actualTool = toolName.includes(\"_\") && toolName.startsWith(server + \"_\")\n ? toolName.slice(server.length + 1)\n : toolName;\n const result: any = await entry.client.callTool({ name: actualTool, arguments: toolArgs });\n return res.json(result);\n } catch (e:any){\n console.error(\"MCP call error:\", e);\n return res.status(500).json({ error: e?.message || \"MCP call failed\" });\n }\n });\n\n // ---- Browser-configured MCP (http only, stateless: connect per request) ----\n async function withUserMcp<T>(cfg: any, fn: (c: Client) => Promise<T>): Promise<T> {\n const u = await assertPublicUrl(String(cfg?.url || \"\"));\n const headers: Record<string, string> = {};\n if (cfg?.headers && typeof cfg.headers === \"object\") {\n for (const [k, v] of Object.entries(cfg.headers)) if (typeof v === \"string\" && /^[\\w-]+$/.test(k)) headers[k] = v;\n }\n const transport = new StreamableHTTPClientTransport(u, { requestInit: { headers } } as any);\n const client = new Client({ name: \"fanluc\", version: \"1.0.0\" } as any, { capabilities: {} } as any);\n let timer: any;\n try {\n const run = (async () => { await client.connect(transport); return fn(client); })();\n return await Promise.race([run, new Promise<never>((_, rej) => { timer = setTimeout(() => rej(new Error(\"MCP timeout (20s)\")), 20000); })]);\n } finally {\n clearTimeout(timer);\n try { await client.close(); } catch {}\n }\n }\n\n app.post(\"/api/mcp/user/probe\", async (req, res) => {\n const list = Array.isArray(req.body?.servers) ? req.body.servers.slice(0, 8) : [];\n const out = await Promise.all(list.map(async (s: any) => {\n const name = String(s?.name || \"\").replace(/[^a-zA-Z0-9_-]/g, \"_\").slice(0, 40);\n try {\n const tools = await withUserMcp(s, async (c) => { const r: any = await c.listTools(); return Array.isArray(r?.tools) ? r.tools : []; });\n const t = tools.map((x: any) => ({ ...x, description: typeof x.description === \"string\" ? x.description : x.description }));\n return { name, type: \"http\", status: \"connected\", tools: t, toolCount: t.length, error: null, source: \"browser\" };\n } catch (e: any) {\n return { name, type: \"http\", status: \"failed\", tools: [], toolCount: 0, error: e?.message || String(e), source: \"browser\" };\n }\n }));\n res.json({ servers: out });\n });\n\n app.post(\"/api/mcp/user/call\", async (req, res) => {\n try {\n const { server, tool, args } = req.body || {};\n if (!server || !tool) return res.status(400).json({ error: \"Missing server or tool\" });\n const name = String(server.name || \"\");\n const actual = String(tool).startsWith(name + \"_\") ? String(tool).slice(name.length + 1) : String(tool);\n const r = await withUserMcp(server, (c) => c.callTool({ name: actual, arguments: args && typeof args === \"object\" ? args : {} }));\n return res.json(r);\n } catch (e: any) {\n return res.status(500).json({ error: e?.message || \"MCP call failed\" });\n }\n });\n\n app.post(\"/api/mcp/reconnect\", mcpAdminGuard, async (req, res) => {\n try {\n const { server } = req.body || {};\n if (!server) return res.status(400).json({ error: \"Missing server\" });\n const cfgMap = loadMcpConfigSync();\n const cfg = cfgMap[server];\n if (!cfg) return res.status(404).json({ error: \"Server not found in mcp.json\" });\n // Close old client if exists\n const old = mcp.get(server);\n try { await (old?.client as any)?.close?.(); } catch {}\n await connectMcp(server, cfg);\n const entry = mcp.get(server)!;\n return res.json({ name: server, status: entry.status, toolCount: entry.tools.length, error: entry.error || null });\n } catch (e:any){ return res.status(500).json({ error: e?.message });}\n });\n\n app.post(\"/api/mcp/toggle\", mcpAdminGuard, async (req, res) => {\n try {\n const { server, enabled } = req.body || {};\n if (!server) return res.status(400).json({ error: \"Missing server\" });\n const cfgMap = loadMcpConfigSync();\n // If server not in file, check memory\n let cfg = cfgMap[server];\n if (!cfg) {\n const mem = mcp.get(server);\n if (!mem) return res.status(404).json({ error: \"Server not found\" });\n cfg = mem.config;\n }\n const newEnabled = enabled !== undefined ? !!enabled : mcp.get(server)?.status === \"disabled\";\n const newCfg = { ...cfg, enabled: newEnabled, disabled: !newEnabled };\n if (newEnabled) {\n await connectMcp(server, newCfg);\n } else {\n const old = mcp.get(server);\n try { await (old?.client as any)?.close?.(); } catch {}\n mcp.set(server, { client: null, tools: [], status: \"disabled\", config: newCfg, type: normalizeMcpType(newCfg.type) });\n }\n // Persist the enabled flag so the choice survives a restart\n try {\n const mcpPath = mcpConfigPath();\n const existing = readMcpServersFile(mcpPath);\n if (existing[server]) {\n existing[server] = { ...existing[server], enabled: newEnabled };\n delete existing[server].disabled;\n fs.writeFileSync(mcpPath, JSON.stringify({ mcpServers: existing }, null, 2), \"utf-8\");\n }\n } catch (e: any) { console.warn(\"[MCP] could not persist toggle:\", e?.message); }\n const entry = mcp.get(server)!;\n return res.json({ name: server, status: entry.status, enabled: newEnabled });\n } catch (e:any){ return res.status(500).json({ error: e?.message });}\n });\n\n app.post(\"/api/mcp/add\", mcpAdminGuard, async (req, res) => {\n try {\n const { name, type, command, args, url, headers, env, enabled = true } = req.body || {};\n if (!name || typeof name !== \"string\") return res.status(400).json({ error: \"Missing name\" });\n const cleanName = name.trim().replace(/[^a-zA-Z0-9_-]/g, \"_\");\n if (!cleanName) return res.status(400).json({ error: \"Invalid name\" });\n // Security: only allow server-side file write; validate inputs\n const newCfg: any = { type: type || (url ? \"http\" : \"stdio\"), enabled: !!enabled };\n if (newCfg.type === \"http\" || newCfg.type === \"remote\") {\n if (!url || !String(url).startsWith(\"http\")) return res.status(400).json({ error: \"Invalid url for http server\" });\n newCfg.url = String(url);\n if (headers && typeof headers === \"object\") newCfg.headers = headers;\n } else {\n if (!command || typeof command !== \"string\") return res.status(400).json({ error: \"Missing command for stdio server\" });\n newCfg.command = String(command);\n if (Array.isArray(args) && args.length) newCfg.args = args.map(String);\n else if (typeof args === \"string\" && args.trim()) newCfg.args = String(args).trim().split(/\\s+/);\n if (env && typeof env === \"object\") newCfg.env = env;\n }\n // Persist to <configDir>/mcp.json (the file the loader actually reads)\n const mcpPath = mcpConfigPath();\n let existing: Record<string, any> = {};\n try { existing = readMcpServersFile(mcpPath); }\n catch (e: any) { return res.status(500).json({ error: \"mcp.json is invalid, refusing to overwrite: \" + (e?.message || e) }); }\n existing[cleanName] = newCfg;\n const toWrite = { mcpServers: existing };\n fs.writeFileSync(mcpPath, JSON.stringify(toWrite, null, 2));\n await connectMcp(cleanName, newCfg);\n const entry = mcp.get(cleanName)!;\n return res.json({ name: cleanName, status: entry.status, toolCount: entry.tools.length, error: entry.error || null });\n } catch (e:any){ return res.status(500).json({ error: e?.message });}\n });\n\n\n // Fetch URL endpoint - extracts clean article text via Readability instead\n // of dumping the whole stripped-tag page (nav/ads/footer/comment junk).\n app.post(\"/api/fetch-url\", async (req, res) => {\n const errorFallback = \"you entered an incorrect URL, are missing characters, or the website no longer exists\";\n try {\n const { url, length = 1100 } = req.body;\n if (!url || typeof url !== \"string\") {\n return res.json({\n url: url || \"\",\n text: errorFallback,\n formattedText: errorFallback,\n });\n }\n\n // Extract valid URL even if AI attached trailing titles, colons or spaces\n const urlMatch = url.match(/https?:\\/\\/[^\\s\"']+/);\n let targetUrl = urlMatch ? urlMatch[0] : url.trim();\n\n try {\n new URL(targetUrl);\n } catch {\n return res.json({\n url: targetUrl,\n text: errorFallback,\n formattedText: errorFallback,\n });\n }\n\n targetUrl = applyDomainRewrite(targetUrl);\n\n let hostname = \"\";\n try {\n hostname = new URL(targetUrl).hostname.toLowerCase();\n } catch {\n // already validated above, shouldn't happen\n }\n\n if (isBlockedHost(hostname)) {\n const blockedMsg = `This site (${hostname}) blocks automated crawling or requires login, so its content cannot be reliably extracted. Try a different, publicly accessible source instead.`;\n return res.json({\n url: targetUrl,\n text: blockedMsg,\n formattedText: `fetched url: ${targetUrl}\\ntext: ${blockedMsg}`,\n });\n }\n\n if (looksLikeNonHtmlFile(targetUrl)) {\n const fileMsg = \"This URL points to a non-HTML file (document, image, archive, or media) and cannot be read as article text.\";\n return res.json({\n url: targetUrl,\n text: fileMsg,\n formattedText: `fetched url: ${targetUrl}\\ntext: ${fileMsg}`,\n });\n }\n\n const cleanLength = Math.min(10000, Math.max(100, parseInt(length) || 1100));\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 20000); // 20s timeout\n\n let fetchResult: { ok: boolean; status: number; contentType: string; body: string };\n try {\n fetchResult = await fetchWithByteLimit(targetUrl, controller.signal, MAX_FETCH_BYTES);\n } finally {\n clearTimeout(timeoutId);\n }\n\n if (!fetchResult.ok) {\n return res.json({\n url: targetUrl,\n text: errorFallback,\n formattedText: errorFallback,\n });\n }\n\n if (fetchResult.contentType && !/text\\/html|application\\/xhtml/i.test(fetchResult.contentType)) {\n const nonHtmlMsg = `This URL returned non-HTML content (${fetchResult.contentType.split(\";\")[0]}) and cannot be read as article text.`;\n return res.json({\n url: targetUrl,\n text: nonHtmlMsg,\n formattedText: `fetched url: ${targetUrl}\\ntext: ${nonHtmlMsg}`,\n });\n }\n\n const { title, text: extractedFull } = extractReadableContent(fetchResult.body, targetUrl);\n\n if (!extractedFull) {\n return res.json({\n url: targetUrl,\n text: errorFallback,\n formattedText: errorFallback,\n });\n }\n\n const extracted = extractedFull.slice(0, cleanLength);\n const titlePart = title ? `title: ${title}\\n` : \"\";\n const formattedText = `fetched url: ${targetUrl}\\n${titlePart}text: ${extracted}`;\n\n return res.json({\n url: targetUrl,\n title,\n text: extracted,\n formattedText,\n });\n } catch (error: any) {\n console.error(\"Fetch URL error:\", error);\n return res.json({\n url: req.body?.url,\n text: errorFallback,\n formattedText: errorFallback,\n });\n }\n });\n\n // Read doc from /docs endpoint\n app.post(\"/api/read-doc\", async (req, res) => {\n try {\n const { name } = req.body;\n if (!name || typeof name !== \"string\") {\n return res.status(400).json({ error: \"Missing name parameter\" });\n }\n\n const cleanName = name.trim().toLowerCase().replace(/^['\"`]|['\"`]$/g, \"\");\n const docsDir = path.join(process.cwd(), \"docs\");\n\n try {\n const files = await fs.promises.readdir(docsDir);\n let targetFile = files.find(\n (f) => f.toLowerCase() === cleanName || f.toLowerCase() === `${cleanName}.md`\n );\n\n if (!targetFile) {\n if (cleanName.includes(\"fanluc\")) targetFile = files.find((f) => f.includes(\"fanluc\"));\n else if (cleanName.includes(\"guide\")) targetFile = files.find((f) => f.includes(\"guide\"));\n else if (cleanName.includes(\"mondk\")) targetFile = files.find((f) => f.includes(\"mondk\"));\n else if (cleanName.includes(\"msh\")) targetFile = files.find((f) => f.includes(\"msh\"));\n else targetFile = files.find((f) => f.toLowerCase().includes(cleanName));\n }\n\n if (targetFile) {\n const content = await fs.promises.readFile(path.join(docsDir, targetFile), \"utf-8\");\n return res.json({\n found: true,\n fileName: targetFile,\n content,\n formattedText: `doc: ${targetFile}\\ncontent:\\n${content}`,\n });\n }\n\n return res.json({\n found: false,\n fileName: name,\n content: `Doc '${name}' not found in /docs/`,\n formattedText: `Doc '${name}' not found in /docs/`,\n });\n } catch (err: any) {\n return res.json({\n found: false,\n fileName: name,\n content: `Error reading docs directory: ${err?.message}`,\n formattedText: `Error reading docs directory: ${err?.message}`,\n });\n }\n } catch (error: any) {\n return res.status(500).json({ error: error?.message || \"Failed to read doc\" });\n }\n });\n\n // Translation endpoint using google-translate-api-x\n app.post(\"/api/translate\", async (req, res) => {\n try {\n const { text, to = \"en\", from = \"auto\" } = req.body;\n if (!text || typeof text !== \"string\") {\n return res.status(400).json({ error: \"Missing text parameter\" });\n }\n\n const cleanText = text.trim();\n if (!cleanText) {\n return res.status(400).json({ error: \"Empty text parameter\" });\n }\n\n const result = await translate(cleanText, {\n to: to || \"en\",\n from: from || \"auto\",\n });\n\n const translatedText = typeof result?.text === \"string\" ? result.text : String(result?.text ?? \"\");\n const detectedFrom = result?.from?.language?.iso || from || \"auto\";\n\n return res.json({\n translatedText,\n detectedFrom,\n originalText: cleanText,\n targetLang: to,\n formattedText: `translated \"${cleanText}\" (${detectedFrom} -> ${to}): \"${translatedText}\"`,\n });\n } catch (error: any) {\n console.error(\"Translation API error:\", error);\n return res.status(500).json({\n error: error?.message || \"Translation failed\",\n translatedText: \"\",\n detectedFrom: req.body?.from || \"auto\",\n formattedText: `translation failed: ${error?.message || \"error\"}`,\n });\n }\n });\n\n // Weather endpoint for show_weather\n app.get(\"/api/weather\", async (req, res) => {\n try {\n const { lat, lon, city } = req.query;\n let finalLat = lat;\n let finalLon = lon;\n let locationName = \"Unknown Location\";\n\n if (city && city !== \"auto\") {\n // Geocode city using Open-Meteo\n const geoRes = await fetch(`https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(String(city))}&count=1&language=en&format=json`);\n const geoData = await geoRes.json();\n if (geoData.results && geoData.results.length > 0) {\n finalLat = geoData.results[0].latitude;\n finalLon = geoData.results[0].longitude;\n locationName = geoData.results[0].name + (geoData.results[0].country ? `, ${geoData.results[0].country}` : \"\");\n } else {\n return res.status(404).json({ error: \"City not found\" });\n }\n } else if (lat && lon) {\n // Reverse geocode for name using BigDataCloud free client API\n try {\n const revGeoRes = await fetch(`https://api.bigdatacloud.net/data/reverse-geocode-client?latitude=${lat}&longitude=${lon}&localityLanguage=en`);\n const revGeoData = await revGeoRes.json();\n locationName = revGeoData.city || revGeoData.locality || revGeoData.principalSubdivision || \"Your Location\";\n } catch (e) {\n locationName = \"Your Location\";\n }\n } else {\n return res.status(400).json({ error: \"Provide lat/lon or city\" });\n }\n\n // Fetch weather using Open-Meteo\n const weatherRes = await fetch(`https://api.open-meteo.com/v1/forecast?latitude=${finalLat}&longitude=${finalLon}¤t_weather=true`);\n const weatherData = await weatherRes.json();\n\n if (!weatherData.current_weather) {\n return res.status(500).json({ error: \"Weather data not available\" });\n }\n\n const current = weatherData.current_weather;\n // Map WMO weather code to condition\n const code = current.weathercode;\n let condition = \"Clear\";\n if (code === 0) condition = \"Sunny\"; // Clear sky\n else if (code === 1 || code === 2 || code === 3) condition = \"Cloudy\"; // Mainly clear, partly cloudy, and overcast\n else if (code === 45 || code === 48) condition = \"Fog\";\n else if (code >= 51 && code <= 67) condition = \"Rainy\"; // Drizzle and Rain\n else if (code >= 71 && code <= 77) condition = \"Snow\";\n else if (code >= 80 && code <= 82) condition = \"Rainy\"; // Rain showers\n else if (code >= 85 && code <= 86) condition = \"Snow\"; // Snow showers\n else if (code >= 95 && code <= 99) condition = \"Stormy\"; // Thunderstorm\n\n // Determine if Windy based on windspeed (rough estimation)\n if (current.windspeed > 20 && (condition === \"Sunny\" || condition === \"Cloudy\" || condition === \"Clear\")) {\n condition = \"Windy\";\n }\n\n res.json({\n location: locationName,\n temperature: current.temperature,\n condition,\n isDay: current.is_day === 1,\n time: current.time,\n });\n } catch (error: any) {\n console.error(\"Weather API error:\", error);\n res.status(500).json({ error: \"Failed to fetch weather\" });\n }\n });\n\n // Permission helper (3 ch\u1EBF \u0111\u1ED9: ask / autoEdit / readOnly)\n function getPermissionMode(): string {\n const m = (process.env.FANLUC_PERMISSION || \"\").trim();\n if (m === \"readOnly\" || m === \"autoEdit\" || m === \"ask\") return m;\n // fallback: try reading settings.json from config dir (strip BOM)\n try {\n const cfgDir = getFanlucConfigDir();\n const p = path.join(cfgDir, \"settings.json\");\n if (fs.existsSync(p)) {\n const raw = fs.readFileSync(p, \"utf-8\").replace(/^\\uFEFF/, \"\");\n const j = JSON.parse(raw);\n if (j.permission === \"readOnly\" || j.permission === \"autoEdit\" || j.permission === \"ask\") return j.permission;\n }\n } catch {}\n return \"ask\";\n }\n\n // FANLUC.md \u2014 workspace context endpoint (for G\u01101: auto-inject into system prompt)\n function loadFanlucMdSync(): { path: string; content: string } | null {\n const candidates = [\n path.join(WORKSPACE_DIR, \"FANLUC.md\"),\n path.join(WORKSPACE_DIR, \"fanluc.md\"),\n path.join(WORKSPACE_DIR, \".fanluc\", \"FANLUC.md\"),\n ];\n for (const p of candidates) {\n try {\n if (fs.existsSync(p) && fs.statSync(p).isFile()) {\n const raw = fs.readFileSync(p, \"utf-8\").replace(/^\\uFEFF/, \"\");\n const MAX = 6000;\n const content = raw.length > MAX ? raw.slice(0, MAX) + \"\\n\\n[... truncated ...]\" : raw;\n return { path: p, content };\n }\n } catch {}\n }\n return null;\n }\n\n app.get(\"/api/fanluc-md\", (_req, res) => {\n const md = loadFanlucMdSync();\n if (!md) return res.json({ found: false, path: null, content: \"\" });\n return res.json({ found: true, path: md.path, content: md.content });\n });\n\n app.get(\"/api/config\", (_req, res) => {\n const cfgDir = getFanlucConfigDir();\n const perm = getPermissionMode();\n const ws = WORKSPACE_DIR;\n const md = loadFanlucMdSync();\n res.json({\n workspace: ws,\n configDir: cfgDir,\n permission: perm,\n fanlucMd: md ? { path: md.path, length: md.content.length } : null,\n platform: process.platform,\n });\n });\n\n // Permission endpoints (Fix 2: ask c\u1EA7n x\u00E1c nh\u1EADn qua ConfirmModal)\n app.get(\"/api/permission/status\", (_req, res) => {\n const perm = getPermissionMode();\n res.json({\n permission: perm,\n fileGranted: isGranted(\"file\"),\n shellGranted: isGranted(\"shell\"),\n ttlMs: GRANT_TTL_MS,\n });\n });\n app.post(\"/api/permission/approve\", (req, res) => {\n const { type } = req.body || {};\n const t = type === \"file\" ? \"file\" : type === \"shell\" ? \"shell\" : \"all\";\n const perm = getPermissionMode();\n if (perm === \"readOnly\") {\n return res.status(403).json({ error: \"readOnly: cannot grant permission\" });\n }\n grantPermission(t as any);\n res.json({ ok: true, granted: t, until: Date.now() + GRANT_TTL_MS });\n });\n app.post(\"/api/permission/mode\", (req, res) => {\n const m = String(req.body?.mode || \"\");\n if (m !== \"ask\" && m !== \"autoEdit\" && m !== \"readOnly\") return res.status(400).json({ error: \"mode must be ask | autoEdit | readOnly\" });\n process.env.FANLUC_PERMISSION = m;\n return res.json({ ok: true, permission: m });\n });\n\n app.post(\"/api/permission/reset\", (_req, res) => {\n clearGrants();\n res.json({ ok: true });\n });\n\n // run_cmd \u2014 real, sandboxed shell execution. See the layered-defense\n // comment near WORKSPACE_DIR/SAFE_ENV/DANGEROUS_PATTERNS above.\n // Windows: PowerShell sandbox, permission ask blocks by default\n app.post(\"/api/run-cmd\", (req, res) => {\n if (process.env.DISABLE_RUN_CMD === \"1\") {\n const msg = \"run_cmd is disabled on this server.\";\n return res.json({ stdout: \"\", stderr: msg, formattedText: msg, blocked: true });\n }\n const perm = getPermissionMode();\n // Fix 2: ask ch\u1EB7n shell cho t\u1EDBi khi ConfirmModal approve; autoEdit c\u0169ng ch\u1EB7n shell\n const needShellGrant = perm === \"ask\" || perm === \"autoEdit\";\n if (perm === \"readOnly\" || (needShellGrant && !isGranted(\"shell\"))) {\n const hint = perm === \"readOnly\"\n ? \"readOnly \u2014 shell disabled\"\n : `permission '${perm}' requires confirmation via web ConfirmModal or POST /api/permission/approve {type:'shell'}`;\n const msg = `Blocked by permission mode '${perm}': shell execution requires confirmation. ${hint}`;\n return res.status(403).json({ stdout: \"\", stderr: msg, formattedText: msg, blocked: true, needConfirm: true, permission: perm });\n }\n const { command } = req.body || {};\n if (!command || typeof command !== \"string\" || !command.trim()) {\n return res.status(400).json({ error: \"Missing command\", formattedText: \"Error: missing command\" });\n }\n const trimmed = preprocessCommand(command.trim());\n\n const blockedReason = findBlockedPattern(trimmed);\n if (blockedReason) {\n const msg = `Command blocked for safety: ${blockedReason}.`;\n return res.json({ stdout: \"\", stderr: msg, formattedText: msg, blocked: true });\n }\n\n const TIMEOUT_MS = 20000;\n const MAX_BUFFER = 2 * 1024 * 1024; // 2MB\n\n let bin: string;\n let args: string[];\n if (IS_WINDOWS) {\n // Windows: always use PowerShell (reliable). WSL's bash.exe is a stub that requires a distribution\n // and would break `echo`, `dir`, etc. Git Bash is optional but PowerShell handles\n // `echo`, `dir`, `python`, `node` etc. via aliases/callable executables.\n bin = \"powershell.exe\";\n // Windows PowerShell 5.1 defaults to the OEM/ANSI code page: force UTF-8 for console output and\n // for the cmdlets that read/write files (Get-Content would otherwise garble BOM-less UTF-8).\n const PS_UTF8 =\n \"[Console]::OutputEncoding=[System.Text.UTF8Encoding]::new($false);\" +\n \"$OutputEncoding=[Console]::OutputEncoding;\" +\n \"$PSDefaultParameterValues['Get-Content:Encoding']='utf8';\" +\n \"$PSDefaultParameterValues['Set-Content:Encoding']='utf8';\" +\n \"$PSDefaultParameterValues['Add-Content:Encoding']='utf8';\" +\n \"$PSDefaultParameterValues['Out-File:Encoding']='utf8';\";\n args = [\"-NoProfile\", \"-Command\", PS_UTF8 + trimmed];\n } else if (FIREJAIL_AVAILABLE) {\n bin = \"firejail\";\n args = [\n \"--quiet\",\n \"--noprofile\",\n `--private=${WORKSPACE_DIR}`,\n \"--net=none\",\n \"--rlimit-fsize=50000000\",\n \"--rlimit-as=1073741824\",\n \"bash\",\n \"-c\",\n trimmed,\n ];\n } else {\n bin = \"bash\";\n args = [\"-c\", trimmed];\n }\n\n execFile(\n bin,\n args,\n { cwd: WORKSPACE_DIR, timeout: TIMEOUT_MS, maxBuffer: MAX_BUFFER, env: SAFE_ENV },\n (err: any, stdout, stderr) => {\n const out = (stdout || \"\").toString().slice(0, 20000);\n const errOut = (stderr || \"\").toString().slice(0, 20000);\n\n if (err && err.killed) {\n const msg = `Command timed out (${TIMEOUT_MS / 1000}s limit).`;\n return res.json({ stdout: out, stderr: msg, formattedText: `$ ${trimmed}\\n${out}\\n${msg}`.trim(), timedOut: true });\n }\n\n const exitCode = err ? (typeof err.code === \"number\" ? err.code : 1) : 0;\n const body = `${out}${errOut ? (out ? \"\\n\" : \"\") + errOut : \"\"}`.trim() || \"(no output)\";\n const formattedText = `$ ${trimmed}\\n${body}`;\n\n return res.json({ stdout: out, stderr: errOut, exitCode, formattedText });\n }\n );\n });\n\n // Upload workspace file endpoint (permission-aware, Fix 2)\n app.post(\"/api/upload-workspace-file\", express.json({ limit: \"10mb\" }), async (req, res) => {\n const perm = getPermissionMode();\n if (perm === \"readOnly\" || (perm === \"ask\" && !isGranted(\"file\"))) {\n const hint = perm === \"ask\" ? \"requires confirmation via ConfirmModal or POST /api/permission/approve {type:'file'}\" : \"readOnly\";\n return res.status(403).json({ error: `Blocked by permission mode '${perm}': file write ${hint}`, needConfirm: perm === \"ask\", permission: perm });\n }\n try {\n const { name, content, encoding = \"utf-8\" } = req.body || {};\n if (!name || typeof name !== \"string\") {\n return res.status(400).json({ error: \"Missing file name\" });\n }\n const cleanName = name.trim().replace(/^(\\.\\/|\\/)+/, \"\");\n const filePath = path.join(WORKSPACE_DIR, cleanName);\n\n const dir = path.dirname(filePath);\n if (!isInsideWorkspace(dir)) {\n return res.status(403).json({ error: \"Invalid file path outside workspace\" });\n }\n await fs.promises.mkdir(dir, { recursive: true });\n\n let buffer: Buffer;\n if ((encoding === \"base64\" || cleanName.toLowerCase().endsWith(\".zip\")) && typeof content === \"string\") {\n let rawBase64 = content;\n if (rawBase64.includes(\",\")) {\n rawBase64 = rawBase64.split(\",\")[1];\n }\n buffer = Buffer.from(rawBase64, \"base64\");\n } else if (typeof content === \"string\") {\n buffer = Buffer.from(content, \"utf-8\");\n } else {\n buffer = Buffer.from(\"\");\n }\n\n await fs.promises.writeFile(filePath, buffer);\n const stats = await fs.promises.stat(filePath);\n\n return res.json({\n success: true,\n path: cleanName,\n name: path.basename(cleanName),\n size: stats.size,\n updatedAt: stats.mtimeMs,\n });\n } catch (err: any) {\n console.error(\"Upload workspace file error:\", err);\n return res.status(500).json({ error: err?.message || \"Failed to upload workspace file\" });\n }\n });\n\n // Delete workspace file endpoint (permission-aware, Fix 2)\n app.post(\"/api/delete-workspace-file\", express.json(), async (req, res) => {\n const perm = getPermissionMode();\n if (perm === \"readOnly\" || (perm === \"ask\" && !isGranted(\"file\"))) {\n const hint = perm === \"ask\" ? \"requires confirmation via ConfirmModal or POST /api/permission/approve {type:'file'}\" : \"readOnly\";\n return res.status(403).json({ error: `Blocked by permission mode '${perm}': file delete ${hint}`, needConfirm: perm === \"ask\", permission: perm });\n }\n try {\n const { path: filePathParam } = req.body || {};\n if (!filePathParam || typeof filePathParam !== \"string\") {\n return res.status(400).json({ error: \"Missing file path\" });\n }\n const cleanName = filePathParam.trim().replace(/^(\\.\\/|\\/)+/, \"\");\n const targetPath = path.join(WORKSPACE_DIR, cleanName);\n\n if (!isInsideWorkspace(targetPath)) {\n return res.status(403).json({ error: \"Invalid file path outside workspace\" });\n }\n\n if (fs.existsSync(targetPath)) {\n await fs.promises.rm(targetPath, { recursive: true, force: true });\n }\n\n return res.json({ success: true, path: cleanName });\n } catch (err: any) {\n console.error(\"Delete workspace file error:\", err);\n return res.status(500).json({ error: err?.message || \"Failed to delete workspace file\" });\n }\n });\n\n // List workspace files endpoint\n app.get(\"/api/workspace-files\", async (_req, res) => {\n try {\n const filesMap: Record<string, any> = {};\n\n async function walkDir(currentDir: string, relativeDir: string = \"\") {\n let entries: fs.Dirent[] = [];\n try {\n entries = await fs.promises.readdir(currentDir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (entry.name.startsWith(\".\") || entry.name === \"node_modules\") continue;\n\n const fullPath = path.join(currentDir, entry.name);\n const relPath = relativeDir ? `${relativeDir}/${entry.name}` : entry.name;\n\n if (entry.isDirectory()) {\n await walkDir(fullPath, relPath);\n } else if (entry.isFile()) {\n try {\n const stats = await fs.promises.stat(fullPath);\n if (stats.size <= 2 * 1024 * 1024) {\n const ext = entry.name.split(\".\").pop()?.toLowerCase() || \"\";\n const isBinary = [\"zip\", \"gz\", \"tar\", \"tgz\", \"rar\", \"7z\", \"png\", \"jpg\", \"jpeg\", \"gif\", \"pdf\", \"exe\", \"bin\", \"apk\", \"iso\"].includes(ext);\n let content = \"\";\n let fileEncoding = \"utf-8\";\n if (isBinary) {\n content = `[Binary File: ${entry.name} (${(stats.size / 1024).toFixed(1)} KB)]`;\n } else {\n try {\n const dec = decodeTextBuffer(await fs.promises.readFile(fullPath));\n content = dec.text;\n fileEncoding = dec.encoding;\n } catch {\n content = `[Unreadable File: ${(stats.size / 1024).toFixed(1)} KB]`;\n }\n }\n filesMap[relPath] = {\n path: relPath,\n name: entry.name,\n content: content,\n size: stats.size,\n language: ext,\n encoding: fileEncoding,\n updatedAt: stats.mtimeMs,\n };\n } else {\n filesMap[relPath] = {\n path: relPath,\n name: entry.name,\n content: `[Large File: ${(stats.size / 1024).toFixed(1)} KB]`,\n size: stats.size,\n language: entry.name.split(\".\").pop()?.toLowerCase() || \"binary\",\n updatedAt: stats.mtimeMs,\n };\n }\n } catch {\n // Ignore unreadable binary files\n }\n }\n }\n }\n\n await walkDir(WORKSPACE_DIR);\n\n return res.json({ files: filesMap });\n } catch (err: any) {\n return res.status(500).json({ error: err?.message || \"Failed to list workspace files\" });\n }\n });\n\n app.get(\"/api/health\", (_req, res) => {\n res.json({ status: \"ok\", workspace: WORKSPACE_DIR, permission: getPermissionMode(), platform: process.platform });\n });\n\n if (process.env.NODE_ENV !== \"production\") {\n const vite = await createViteServer({\n server: { middlewareMode: true },\n appType: \"spa\",\n });\n app.use(vite.middlewares);\n } else {\n const distPath = path.join(process.cwd(), \"dist\");\n app.use(express.static(distPath));\n app.get(\"*\", (_req, res) => {\n res.sendFile(path.join(distPath, \"index.html\"));\n });\n }\n\n const HOST = process.env.HOST || \"0.0.0.0\";\n // Log startup context (workspace, config, FANLUC.md)\n const cfgDir = getFanlucConfigDir();\n const permMode = getPermissionMode();\n const fanlucMd = loadFanlucMdSync();\n console.log(`[fanluc] Workspace : ${WORKSPACE_DIR}`);\n console.log(`[fanluc] Config dir: ${cfgDir}`);\n console.log(`[fanluc] Permission: ${permMode}`);\n if (fanlucMd) console.log(`[fanluc] FANLUC.md : ${fanlucMd.path} (${fanlucMd.content.length} chars)`);\n else console.log(`[fanluc] FANLUC.md : (none)`);\n\n app.listen(PORT, HOST, () => {\n const displayHost = HOST === \"0.0.0.0\" ? \"localhost\" : HOST;\n console.log(`Server running on http://${displayHost}:${PORT}`);\n console.log(`Health: http://${displayHost}:${PORT}/api/health`);\n });\n}\n\nexport { startServer };\n\n// Auto-start when file is executed directly (both ESM via tsx and CJS via node dist/server.cjs)\n// Skip only if explicitly disabled via FANLUC_NO_AUTO_START=1 (for tests / library import)\nif (process.env.FANLUC_NO_AUTO_START !== \"1\") {\n startServer().catch((e) => {\n console.error(\"Failed to start server:\", e);\n process.exit(1);\n });\n}\n", "/**\n * Decode a file buffer to text without mojibake.\n * Windows tools disagree on encoding: Windows PowerShell 5.1 `>` / Out-File write UTF-16LE (with BOM),\n * Set-Content writes ANSI, editors add a UTF-8 BOM, Node/VS Code write UTF-8 without BOM.\n */\nexport function decodeTextBuffer(buf: Buffer): { text: string; encoding: string } {\n if (buf.length >= 3 && buf[0] === 0xef && buf[1] === 0xbb && buf[2] === 0xbf) {\n return { text: buf.subarray(3).toString(\"utf8\"), encoding: \"utf-8-bom\" };\n }\n if (buf.length >= 2 && buf[0] === 0xff && buf[1] === 0xfe) {\n return { text: buf.subarray(2).toString(\"utf16le\"), encoding: \"utf-16le\" };\n }\n if (buf.length >= 2 && buf[0] === 0xfe && buf[1] === 0xff) {\n const sw = Buffer.from(buf.subarray(2));\n for (let i = 0; i + 1 < sw.length; i += 2) { const t = sw[i]; sw[i] = sw[i + 1]; sw[i + 1] = t; }\n return { text: sw.toString(\"utf16le\"), encoding: \"utf-16be\" };\n }\n // BOM-less UTF-16LE (mostly ASCII text => every other byte is NUL)\n const sample = buf.subarray(0, Math.min(buf.length, 1024));\n let nulOdd = 0, nulTotal = 0;\n for (let i = 0; i < sample.length; i++) if (sample[i] === 0) { nulTotal++; if (i % 2 === 1) nulOdd++; }\n if (sample.length >= 4 && nulTotal > sample.length * 0.2 && nulOdd >= nulTotal * 0.9) {\n return { text: buf.toString(\"utf16le\"), encoding: \"utf-16le\" };\n }\n try {\n return { text: new TextDecoder(\"utf-8\", { fatal: true }).decode(buf), encoding: \"utf-8\" };\n } catch {}\n // Not valid UTF-8: legacy ANSI code page (Vietnamese Windows = 1258).\n try { return { text: new TextDecoder(\"windows-1258\").decode(buf), encoding: \"windows-1258\" }; } catch {}\n return { text: buf.toString(\"latin1\"), encoding: \"latin1\" };\n}\n\n", "/**\n * run_cmd blocklist (G\u01102) \u2014 pure module, kh\u00F4ng ph\u1EE5 thu\u1ED9c server/DOM n\u00EAn test \u0111\u01B0\u1EE3c.\n *\n * Defense-in-depth, KH\u00D4NG ph\u1EA3i sandbox ho\u00E0n ch\u1EC9nh: ch\u1EB7n c\u00E1c pattern ph\u00E1 ho\u1EA1i /\n * \u0111\u00E1nh c\u1EAFp / leo quy\u1EC1n r\u00F5 r\u00E0ng tr\u01B0\u1EDBc khi spawn process.\n *\n * Thay \u0111\u1ED5i so v\u1EDBi G\u01101 (m\u1EE5c 2 trong phan-con-lai-GD1.txt):\n * Tr\u01B0\u1EDBc: m\u1ECDi `Remove-Item ... -Recurse` \u0111\u1EC1u b\u1ECB ch\u1EB7n (k\u1EC3 c\u1EA3 `-Recurse .\\tmp`).\n * Nay: ph\u00E2n t\u00EDch \u0110\u00CDCH xo\u00E1. Ch\u1EC9 ch\u1EB7n khi \u0111\u00EDch nguy hi\u1EC3m:\n * - g\u1ED1c \u1ED5 \u0111\u0129a / \u0111\u01B0\u1EDDng d\u1EABn tuy\u1EC7t \u0111\u1ED1i ngo\u00E0i workspace / UNC\n * - ~, $HOME, $env:..., %VAR%, bi\u1EBFn/subexpression kh\u00F4ng resolve \u0111\u01B0\u1EE3c\n * - \u0111i l\u00EAn ngo\u00E0i workspace b\u1EB1ng `..`\n * - ch\u00EDnh th\u01B0 m\u1EE5c workspace (khi -Recurse)\n * - wildcard \"tr\u00F9m h\u1EBFt\" (`*`, `.\\*`, `*.*`) khi -Recurse\n * - b\u1EA5t k\u1EF3 wildcard n\u00E0o khi c\u00F3 \u0111\u1EE7 -Recurse + -Force\n * - -Recurse m\u00E0 \u0111\u00EDch \u0111\u1EBFn t\u1EEB pipeline (kh\u00F4ng bi\u1EBFt xo\u00E1 g\u00EC)\n */\nimport path from \"node:path\";\n\nexport interface BlockRule {\n pattern: RegExp;\n reason: string;\n}\n\nexport interface BlockOptions {\n /** Th\u01B0 m\u1EE5c workspace (\u0111\u01B0\u1EDDng d\u1EABn tuy\u1EC7t \u0111\u1ED1i). C\u00F3 th\u00EC m\u1EDBi x\u00E1c \u0111\u1ECBnh \u0111\u01B0\u1EE3c \"ngo\u00E0i workspace\". */\n workspaceDir?: string;\n /** M\u1EB7c \u0111\u1ECBnh process.platform. \"win32\" b\u1EADt th\u00EAm alias rm/del/rd/... c\u1EE7a PowerShell. */\n platform?: NodeJS.Platform;\n}\n\n/** C\u00E1c rule regex \"ph\u1EB3ng\". Rule Remove-Item -Recurse c\u0169 \u0111\u00E3 \u0111\u01B0\u1EE3c thay b\u1EB1ng analyzePowerShellDelete(). */\nexport const DANGEROUS_PATTERNS: BlockRule[] = [\n { pattern: /\\bsudo\\b|\\bsu\\s+(-|root)\\b/i, reason: \"privilege escalation (sudo/su)\" },\n { pattern: /\\brm\\s+(-[a-z]*r[a-z]*f[a-z]*|-[a-z]*f[a-z]*r[a-z]*)\\s+\\/(?!home\\/|tmp\\/|workspace)/i, reason: \"recursive delete outside the workspace\" },\n { pattern: /\\brm\\s+(-[a-z]*r[a-z]*f[a-z]*|-[a-z]*f[a-z]*r[a-z]*)\\s+[~*]\\s*(\\/|$)/i, reason: \"recursive delete of home/root\" },\n { pattern: /:\\(\\)\\s*\\{\\s*:\\s*\\|\\s*:\\s*&?\\s*\\}\\s*;/, reason: \"fork bomb\" },\n { pattern: /\\bmkfs\\b|\\bdd\\s+if=.*of=\\/dev\\/|\\bshred\\b/i, reason: \"disk-level destructive command\" },\n { pattern: /\\b(shutdown|reboot|halt|poweroff)\\b/i, reason: \"system power control\" },\n { pattern: /\\bchmod\\s+.*777\\s+\\//i, reason: \"world-writable permission change on root\" },\n { pattern: /\\b(curl|wget)\\b[^\\n|]*\\|\\s*(sudo\\s+)?(bash|sh|zsh)\\b/i, reason: \"piping a remote script straight into a shell\" },\n { pattern: /\\/etc\\/(passwd|shadow|sudoers)\\b/i, reason: \"reading system credential files\" },\n { pattern: /\\.env\\b/i, reason: \"accessing .env (may contain server secrets, not exposed to run_cmd on purpose)\" },\n { pattern: /\\bnc\\b.*-e\\b|\\/dev\\/tcp\\//i, reason: \"raw reverse-shell / netcat exec pattern\" },\n { pattern: /\\bcrontab\\b/i, reason: \"persistence via crontab\" },\n // --- Windows / PowerShell ---\n { pattern: /\\b(rd|rmdir)\\b[^&|;]*\\/s/i, reason: \"Windows rd/rmdir /s recursive delete\" },\n { pattern: /\\b(del|erase)\\b[^&|;]*\\/s/i, reason: \"Windows del/erase /s recursive delete\" },\n { pattern: /\\b(Format-Volume|Format-C|Clear-Disk|Remove-Partition)\\b/i, reason: \"Windows disk destructive command\" },\n { pattern: /\\b(iwr|Invoke-WebRequest|Invoke-RestMethod|curl|wget)\\b[^\\n|;]*\\|\\s*(iex|Invoke-Expression)\\b/i, reason: \"PowerShell piping remote script into Invoke-Expression (iwr | iex)\" },\n { pattern: /\\biex\\b|\\bInvoke-Expression\\b/i, reason: \"PowerShell Invoke-Expression\" },\n { pattern: /\\b(Start-Process|Invoke-Item)\\b.*\\b(powershell|cmd|wscript|cscript)\\b/i, reason: \"PowerShell spawning shell via Start-Process\" },\n { pattern: /-EncodedCommand\\b/i, reason: \"PowerShell EncodedCommand (obfuscated script)\" },\n { pattern: /\\bFromBase64String\\b/i, reason: \"PowerShell FromBase64String (obfuscated)\" },\n];\n\n// ---------------------------------------------------------------------------\n// Tokenizer t\u1ED1i gi\u1EA3n cho PowerShell: t\u00E1ch theo segment (; | & newline { } ( ))\n// v\u00E0 token (kho\u1EA3ng tr\u1EAFng, d\u1EA5u ph\u1EA9y), c\u00F3 x\u1EED l\u00FD quote '...' v\u00E0 \"...\".\n// ---------------------------------------------------------------------------\n\ninterface Segment {\n tokens: string[];\n /** Segment n\u00E0y \u0111\u1EE9ng ngay sau d\u1EA5u `|` (nh\u1EADn input t\u1EEB pipeline). */\n fromPipe: boolean;\n}\n\nfunction tokenizeSegments(cmd: string): Segment[] {\n const segments: Segment[] = [];\n let tokens: string[] = [];\n let cur = \"\";\n let hasCur = false;\n let curFromPipe = false;\n\n const pushToken = () => {\n if (hasCur) tokens.push(cur);\n cur = \"\";\n hasCur = false;\n };\n const endSegment = (sep: string) => {\n pushToken();\n if (tokens.length) segments.push({ tokens, fromPipe: curFromPipe });\n tokens = [];\n curFromPipe = sep === \"|\"; // segment k\u1EBF ti\u1EBFp nh\u1EADn input t\u1EEB pipeline n\u1EBFu ng\u0103n c\u00E1ch b\u1EDFi `|`\n };\n\n for (let i = 0; i < cmd.length; i++) {\n const ch = cmd[i];\n if (ch === \"'\" || ch === '\"') {\n hasCur = true;\n const q = ch;\n i++;\n while (i < cmd.length) {\n if (cmd[i] === q) {\n if (cmd[i + 1] === q) { cur += q; i += 2; continue; } // '' ho\u1EB7c \"\" = quote literal\n break;\n }\n if (q === '\"' && cmd[i] === \"`\" && i + 1 < cmd.length) { cur += cmd[i + 1]; i += 2; continue; }\n cur += cmd[i++];\n }\n continue;\n }\n if (ch === \";\" || ch === \"\\n\" || ch === \"\\r\" || ch === \"&\" || ch === \"{\" || ch === \"}\" || ch === \"(\" || ch === \")\") {\n endSegment(ch);\n continue;\n }\n if (ch === \"|\") { endSegment(\"|\"); continue; }\n if (ch === \" \" || ch === \"\\t\" || ch === \",\") { pushToken(); continue; }\n cur += ch;\n hasCur = true;\n }\n endSegment(\";\");\n return segments;\n}\n\n// ---------------------------------------------------------------------------\n// Path classification\n// ---------------------------------------------------------------------------\n\nfunction looksWindows(opts: BlockOptions): boolean {\n const ws = opts.workspaceDir || \"\";\n return opts.platform === \"win32\" || /^[a-zA-Z]:[\\\\/]/.test(ws) || ws.startsWith(\"\\\\\\\\\");\n}\n\n/** Wildcard \"tr\u00F9m h\u1EBFt\": *, .\\*, ./*, *.*, ** */\nconst UNIVERSAL_WILDCARD = /^(\\.?[\\\\/])?\\*+(\\.\\*)?$/;\n\nfunction classifyTarget(rawTarget: string, recurse: boolean, force: boolean, opts: BlockOptions): string | null {\n const t = rawTarget.trim();\n if (!t) return null;\n\n // Home / env / bi\u1EBFn kh\u00F4ng resolve \u0111\u01B0\u1EE3c \u2014 lu\u00F4n nguy hi\u1EC3m (k\u1EC3 c\u1EA3 kh\u00F4ng recurse, gi\u1ED1ng rule G\u01101)\n if (t === \"~\" || /^~[\\\\/]/.test(t) || /\\$home\\b/i.test(t) || /\\$env:/i.test(t) || /%[^%]+%/.test(t)) {\n return \"target is home directory or environment path (~, $HOME, $env:, %VAR%)\";\n }\n if (recurse && (/\\$/.test(t) || /`/.test(t))) {\n return \"recursive delete with a target that cannot be resolved statically (variable / subexpression)\";\n }\n\n const hasWildcard = /[*?]/.test(t);\n if (recurse && UNIVERSAL_WILDCARD.test(t)) {\n return \"recursive delete of everything via wildcard (*)\";\n }\n if (recurse && force && hasWildcard) {\n return \"recursive + force delete with a wildcard target\";\n }\n\n const isWin = looksWindows(opts);\n const p = isWin ? path.win32 : path.posix;\n const isAbs =\n /^[a-zA-Z]:/.test(t) || t.startsWith(\"\\\\\\\\\") || t.startsWith(\"\\\\\") || t.startsWith(\"/\") || p.isAbsolute(t);\n\n // \u0110\u01B0\u1EDDng d\u1EABn ki\u1EC3u Windows (C:\\, \\\\server, \\x) kh\u00F4ng th\u1EC3 n\u1EB1m trong workspace POSIX\n if (!isWin && (/^[a-zA-Z]:/.test(t) || t.startsWith(\"\\\\\"))) {\n return \"target is a Windows-style absolute path outside the workspace\";\n }\n\n const ws = opts.workspaceDir ? p.resolve(opts.workspaceDir) : null;\n const norm = (s: string) => (isWin ? s.toLowerCase() : s);\n\n // B\u1ECF ph\u1EA7n wildcard cu\u1ED1i \u0111\u1EC3 resolve th\u01B0 m\u1EE5c cha (vd .\\build\\* -> .\\build)\n const forResolve = hasWildcard ? t.replace(/[\\\\/]?[^\\\\/]*[*?][^\\\\/]*$/, \"\") || \".\" : t;\n\n if (!ws) {\n // Kh\u00F4ng bi\u1EBFt workspace: ch\u1EC9 cho ph\u00E9p \u0111\u01B0\u1EDDng d\u1EABn t\u01B0\u01A1ng \u0111\u1ED1i kh\u00F4ng ch\u1EE9a `..`\n if (isAbs) return \"absolute path target (workspace unknown)\";\n if (forResolve.split(/[\\\\/]+/).includes(\"..\")) return \"target escapes the workspace (..)\";\n return null;\n }\n\n const resolved = p.resolve(ws, forResolve);\n const rel = p.relative(norm(ws), norm(resolved));\n const escapes = rel === \"..\" || rel.startsWith(\"..\" + p.sep) || p.isAbsolute(rel);\n if (escapes) {\n return isAbs ? \"target is an absolute path outside the workspace\" : \"target escapes the workspace (..)\";\n }\n if (recurse && rel === \"\" && !hasWildcard) {\n return \"recursive delete of the workspace root itself\";\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// PowerShell delete analysis\n// ---------------------------------------------------------------------------\n\nconst PS_ONLY_DELETE = new Set([\"remove-item\", \"ri\"]);\nconst WIN_ALIAS_DELETE = new Set([\"rm\", \"del\", \"erase\", \"rd\", \"rmdir\"]);\nconst VALUE_FLAGS_TARGET = [\"path\", \"literalpath\"];\nconst VALUE_FLAGS_SKIP = [\"include\", \"exclude\", \"filter\", \"credential\", \"stream\"];\n\n/** C\u1EDD PowerShell c\u00F3 th\u1EC3 vi\u1EBFt t\u1EAFt: -Rec, -Recurse, -r ... */\nfunction flagMatches(name: string, full: string, minLen: number): boolean {\n const n = name.toLowerCase();\n return n.length >= minLen && full.startsWith(n);\n}\n\nfunction analyzePowerShellDelete(command: string, opts: BlockOptions): string | null {\n const platform = opts.platform ?? process.platform;\n const heads = new Set(PS_ONLY_DELETE);\n if (platform === \"win32\") for (const a of WIN_ALIAS_DELETE) heads.add(a);\n\n const segments = tokenizeSegments(command);\n let analyzedRemoveItem = 0;\n\n for (const seg of segments) {\n // b\u1ECF qua token \u0111\u1EA7u ki\u1EC3u \".\" (dot-source) v\u00E0 module-qualified name\n const head = (seg.tokens[0] || \"\").toLowerCase().replace(/^.*\\\\/, \"\");\n if (!heads.has(head)) continue;\n if (head === \"remove-item\") analyzedRemoveItem++;\n\n let recurse = false;\n let force = false;\n const targets: string[] = [];\n\n for (let i = 1; i < seg.tokens.length; i++) {\n const tok = seg.tokens[i];\n if (tok.startsWith(\"-\") && tok.length > 1 && !/^-\\d/.test(tok)) {\n const body = tok.slice(1);\n const colon = body.indexOf(\":\");\n const name = colon >= 0 ? body.slice(0, colon) : body;\n const inlineVal = colon >= 0 ? body.slice(colon + 1) : null;\n\n if (flagMatches(name, \"recurse\", 1)) {\n recurse = !(inlineVal && /^\\$?false$/i.test(inlineVal));\n } else if (flagMatches(name, \"force\", 2)) {\n force = !(inlineVal && /^\\$?false$/i.test(inlineVal));\n } else if (VALUE_FLAGS_TARGET.some((f) => flagMatches(name, f, 1))) {\n const v = inlineVal ?? seg.tokens[++i];\n if (v) targets.push(v);\n } else if (VALUE_FLAGS_SKIP.some((f) => flagMatches(name, f, 1))) {\n if (inlineVal === null) i++; // b\u1ECF gi\u00E1 tr\u1ECB \u0111i k\u00E8m\n }\n continue;\n }\n targets.push(tok);\n }\n\n if (recurse && targets.length === 0 && seg.fromPipe) {\n return \"recursive delete with pipeline input (target unknown)\";\n }\n if (recurse && targets.length === 0) {\n return \"recursive delete without an explicit target\";\n }\n for (const t of targets) {\n const why = classifyTarget(t, recurse, force, opts);\n if (why) return `PowerShell delete blocked: ${why}`;\n }\n }\n\n // Remove-Item xu\u1EA5t hi\u1EC7n nh\u01B0ng kh\u00F4ng n\u1EB1m \u1EDF \u0111\u1EA7u segment n\u00E0o (vd. n\u1EB1m trong\n // `powershell -c \"...\"`, `cmd /c ...`, `-Command '...'`): kh\u00F4ng ph\u00E2n t\u00EDch \u0111\u01B0\u1EE3c\n // \u2192 fallback v\u1EC1 h\u00E0nh vi nghi\u00EAm c\u1EE7a G\u01101, ch\u1EC9 cho tr\u01B0\u1EDDng h\u1EE3p c\u00F3 -Recurse.\n const rawCount = (command.match(/\\bRemove-Item\\b/gi) || []).length;\n if (rawCount > analyzedRemoveItem && /-r(e(c(u(r(s(e)?)?)?)?)?)?\\b/i.test(command)) {\n return \"PowerShell recursive delete inside a nested/quoted command (cannot verify target)\";\n }\n return null;\n}\n\n/** Tr\u1EA3 v\u1EC1 l\u00FD do b\u1ECB ch\u1EB7n, ho\u1EB7c null n\u1EBFu cho ph\u00E9p. */\nexport function findBlockedPattern(command: string, opts: BlockOptions = {}): string | null {\n for (const { pattern, reason } of DANGEROUS_PATTERNS) {\n if (pattern.test(command)) return reason;\n }\n return analyzePowerShellDelete(command, opts);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["path", "dotenv", "path", "fs", "findBlockedPattern", "url", "net", "dns", "path", "os", "fs", "express", "responseText", "results", "formattedText", "cfgDir", "findBlockedPattern", "createViteServer"]
|
|
7
|
+
}
|
|
Binary file
|