From 5f1bce4b990eea523c4d771049d2bc8f2e1a0634 Mon Sep 17 00:00:00 2001 From: admin Date: Wed, 18 Mar 2026 20:35:14 +0000 Subject: [PATCH] feat: SEO web audit, URL fetching, auto web search for SEO mode (v1.6.0) --- CHANGELOG.md | 20 ++ README.md | 354 +++++++++++++++++------------------ app/api/fetch-url/route.ts | 117 ++++++++++++ components/AIAssist.tsx | 63 ++++++- fix_device_array.py | 17 ++ fix_device_buttons.py | 46 +++++ fix_device_size.py | 43 +++++ fix_device_size2.py | 33 ++++ fix_reviewcode.py | 31 +++ fix_reviewcode2.py | 18 ++ fix_v1.4.0.py | 210 +++++++++++++++++++++ lib/services/ollama-cloud.ts | 9 +- lib/services/openrouter.ts | 20 +- lib/services/qwen-oauth.ts | 9 +- lib/services/zai-plan.ts | 9 +- package.json | 2 +- 16 files changed, 817 insertions(+), 184 deletions(-) create mode 100644 app/api/fetch-url/route.ts create mode 100644 fix_device_array.py create mode 100644 fix_device_buttons.py create mode 100644 fix_device_size.py create mode 100644 fix_device_size2.py create mode 100644 fix_reviewcode.py create mode 100644 fix_reviewcode2.py create mode 100644 fix_v1.4.0.py diff --git a/CHANGELOG.md b/CHANGELOG.md index d5bf644..4b69c88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,26 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.6.0] - 2026-03-18 20:34 UTC + +### Added +- **SEO Web Audit** — SEO agent can now fetch and analyze live websites + - `/api/fetch-url` route extracts: title, meta tags, headings (h1-h6), links (internal/external), images (alt text coverage), canonical URL, OG tags, text content length + - Auto-detects URLs in user input when SEO agent is active + - Pre-fetches page data before sending to AI for comprehensive audit reports + - Supports up to 2 URLs per request +- **SEO Auto Web Search** — When SEO agent is active and no URL is provided, web search is automatically triggered + - Uses same SearXNG infrastructure as manual web search toggle + - No manual toggle needed in SEO mode +- **Updated SEO Agent Prompt** — All 4 AI services now instruct SEO agent about web audit and search capabilities + - Added `[WEB_AUDIT:url]` and `[WEB_SEARCH:query]` tool markers + - Added "WEB TOOLS" section to system prompts + +### Technical Details +- Files modified: 5 (AIAssist.tsx, qwen-oauth.ts, ollama-cloud.ts, zai-plan.ts, openrouter.ts) +- Files added: 1 (`app/api/fetch-url/route.ts`) +- New API endpoint: `GET /api/fetch-url?url=https://example.com` + ## [1.5.0] - 2026-03-18 20:29 UTC ### Added diff --git a/README.md b/README.md index 7acee7d..1f74f02 100644 --- a/README.md +++ b/README.md @@ -1,179 +1,179 @@ # PromptArch: AI Orchestration Platform -> **Latest Version**: [v1.5.0](CHANGELOG.md#150---2026-03-18) (2026-03-18) - -> **Development Note**: This entire platform was developed exclusively using [TRAE.AI IDE](https://trae.ai) powered by elite [GLM 4.7 model](https://z.ai/subscribe?ic=R0K78RJKNW). -> **Learn more about this architecture [here](https://z.ai/subscribe?ic=R0K78RJKNW).** - ---- - -> **Fork Note**: This project is a specialized fork of [ClavixDev/Clavix](https://github.com/ClavixDev/Clavix), reimagined as a modern web-based platform for visual prompt engineering and product planning. - -Transform vague ideas into production-ready prompts and PRDs. PromptArch is an AI orchestration platform designed for software architects and Vibe Coders, featuring a **plan-first workflow** with multi-provider AI support and live canvas rendering. - -**Developed by Roman | RyzenAdvanced** - -- **Gitea Repository**: [admin/PromptArch](https://github.rommark.dev/admin/PromptArch) -- **Live Site**: [rommark.dev/tools/promptarch](https://rommark.dev/tools/promptarch/) -- **Telegram**: [@VibeCodePrompterSystem](https://t.me/VibeCodePrompterSystem) - -## Core Capabilities - -| Feature | Description | -|---------|-------------| -| **AI Assist** | Plan-first workflow: describe a task, get a structured plan, approve, then generate working code with live preview | -| **Prompt Enhancer** | Refine vague prompts into surgical instructions using 9 enhancement strategies and 11+ intent patterns | -| **PRD Generator** | Convert ideas into structured Product Requirements Documents | -| **Action Plan** | Decompose PRDs into actionable development steps and framework recommendations | -| **Google Ads Generator** | Generate ad campaigns with XLSX and HTML report export | -| **Slides Generator** | Create presentation decks from prompts | -| **Market Researcher** | AI-powered market research and analysis | - -## Features - -### Plan-First Workflow (v1.3.0) -- AI generates a structured plan (architecture, tech stack, files, steps) before any code -- Plan Review Card with **Modify Plan**, **Start Coding**, and **Skip to Code** actions -- After code generation: **Preview** canvas + **Request Modifications** buttons -- Streaming plan mode with real-time parsing and canvas suppression - -### Multi-Provider AI (4 Providers) -| Provider | Auth | Models | -|----------|------|--------| -| **Qwen Code** | OAuth (2,000 free req/day) | Qwen Coder models | -| **Ollama Cloud** | API Key | Open-source models | -| **Z.AI Plan** | API Key | GLM general + coding models | -| **OpenRouter** | API Key | 20+ models (Gemini, Llama, Mistral, etc.) | - -### Visual Canvas -- Live code rendering with `[PREVIEW]` tags -- HTML, React, Python, and more — rendered in-browser -- Auto-detect renderable vs. code-only previews -- Responsive preview with device size selector (Full / Desktop / Tablet / Mobile) - -### Code Review & Web Search -- **Review Code** — Send generated code back to AI for bug/security/performance review -- **Web Search Grounding** — Toggle to enrich prompts with live web search results via SearXNG - -### Enhanced Prompt Engine -- 9 strategies: clarify, add-context, add-constraints, structure, add-examples, set-tone, expand, simplify, chain-of-thought -- Context-aware strategy selection based on detected intent -- 11+ intent detection patterns (coding, creative, analysis, etc.) - -### Other -- Multi-language support (English, Russian, Hebrew) -- Download generated artifacts as ZIP -- Push to GitHub integration -- Resilient multi-tier provider fallbacks - -## Quick Start - -1. **Clone & Install**: - ```bash - git clone https://github.rommark.dev/admin/PromptArch.git - cd PromptArch - npm install - ``` - -2. **Configuration**: - Copy `.env.example` to `.env` and add your API keys: - ```bash - cp .env.example .env - ``` - - Configure at least one provider: - - **Qwen**: Get OAuth credentials from [qwen.ai](https://qwen.ai) - - **Ollama**: Get API key from [ollama.com/cloud](https://ollama.com/cloud) - - **Z.AI**: Get API key from [docs.z.ai](https://docs.z.ai) - - **OpenRouter**: Get API key from [openrouter.ai/keys](https://openrouter.ai/keys) (free tier available) - -3. **Launch**: - ```bash - npm run dev - ``` - -4. Open [http://localhost:3000](http://localhost:3000) to begin. - -## Tech Stack - -- **Framework**: Next.js 15 (App Router, Turbopack) -- **Styling**: Tailwind CSS -- **State Management**: Zustand -- **Components**: shadcn/ui (Radix UI) -- **Icons**: Lucide React -- **Markdown**: react-markdown -- **Language**: TypeScript - -## Project Structure - -``` -promptarch/ - components/ - AIAssist.tsx # Main AI chat with plan-first workflow (1453 lines) - PromptEnhancer.tsx # Prompt enhancement UI with intent detection (556 lines) - SettingsPanel.tsx # Provider configuration and API key management (569 lines) - Sidebar.tsx # Navigation sidebar - GoogleAdsGenerator.tsx # Google Ads campaign generator - PRDGenerator.tsx # Product Requirements Document generator - ActionPlanGenerator.tsx # Action plan decomposition - SlidesGenerator.tsx # Presentation deck generator - MarketResearcher.tsx # Market research tool - HistoryPanel.tsx # Chat history management - lib/ - enhance-engine.ts # Modular prompt enhancement (9 strategies) - store.ts # Zustand state store - artifact-utils.ts # Preview/rendering utilities - export-utils.ts # Export to XLSX/HTML/ZIP - services/ - qwen-oauth.ts # Qwen OAuth streaming service - ollama-cloud.ts # Ollama Cloud streaming service - zai-plan.ts # Z.AI Plan streaming service - openrouter.ts # OpenRouter streaming service - model-adapter.ts # Unified provider adapter - adapter-instance.ts # Provider registry - i18n/ - translations.ts # EN/RU/HE translations - types/ - index.ts # TypeScript interfaces -``` - -## Versioning - -This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). See [CHANGELOG.md](CHANGELOG.md) for detailed release notes. - -| Version | Date | Highlights | -|---------|------|------------| -| [1.4.0](CHANGELOG.md#140---2026-03-18) | 2026-03-18 19:57 | Review Code button, web search grounding, responsive preview, model selector fix | -| [1.3.0](CHANGELOG.md#130---2026-03-18) | 2026-03-18 18:51 | Plan-first workflow, OpenRouter, post-coding UX, enhanced prompt engine | -| [1.2.0](CHANGELOG.md#120---2026-01-19) | 2026-01-19 19:16 | SEO agent fixes, Z.AI API validation | -| [1.1.0](CHANGELOG.md#110---2025-12-29) | 2025-12-29 17:55 | GitHub push, XLSX/HTML export, OAuth management | -| [1.0.0](CHANGELOG.md#100---2025-12-29) | 2025-12-29 13:51 | Initial release | - -## Development - -```bash -npm install # Install dependencies -npm run dev # Development server (Turbopack) -npm run build # Production build -npm start # Start production server -npm run lint # Lint code -``` - -## Attribution & Credits - -**Author**: Roman | RyzenAdvanced -- **Gitea**: [admin/PromptArch](https://github.rommark.dev/admin/PromptArch) -- **Telegram**: [@VibeCodePrompterSystem](https://t.me/VibeCodePrompterSystem) - -**Forked from**: [ClavixDev/Clavix](https://github.com/ClavixDev/Clavix) -- Visual and architectural evolution of the Clavix framework - -**Development Platform**: [TRAE.AI IDE](https://trae.ai) powered by [GLM 4.7](https://z.ai/subscribe?ic=R0K78RJKNW) - -## License - -ISC - -## Contributing - -Contributions are welcome! Please feel free to submit a Pull Request. +> **Latest Version**: [v1.6.0](CHANGELOG.md#160---2026-03-18) (2026-03-18) + +> **Development Note**: This entire platform was developed exclusively using [TRAE.AI IDE](https://trae.ai) powered by elite [GLM 4.7 model](https://z.ai/subscribe?ic=R0K78RJKNW). +> **Learn more about this architecture [here](https://z.ai/subscribe?ic=R0K78RJKNW).** + +--- + +> **Fork Note**: This project is a specialized fork of [ClavixDev/Clavix](https://github.com/ClavixDev/Clavix), reimagined as a modern web-based platform for visual prompt engineering and product planning. + +Transform vague ideas into production-ready prompts and PRDs. PromptArch is an AI orchestration platform designed for software architects and Vibe Coders, featuring a **plan-first workflow** with multi-provider AI support and live canvas rendering. + +**Developed by Roman | RyzenAdvanced** + +- **Gitea Repository**: [admin/PromptArch](https://github.rommark.dev/admin/PromptArch) +- **Live Site**: [rommark.dev/tools/promptarch](https://rommark.dev/tools/promptarch/) +- **Telegram**: [@VibeCodePrompterSystem](https://t.me/VibeCodePrompterSystem) + +## Core Capabilities + +| Feature | Description | +|---------|-------------| +| **AI Assist** | Plan-first workflow: describe a task, get a structured plan, approve, then generate working code with live preview | +| **Prompt Enhancer** | Refine vague prompts into surgical instructions using 9 enhancement strategies and 11+ intent patterns | +| **PRD Generator** | Convert ideas into structured Product Requirements Documents | +| **Action Plan** | Decompose PRDs into actionable development steps and framework recommendations | +| **Google Ads Generator** | Generate ad campaigns with XLSX and HTML report export | +| **Slides Generator** | Create presentation decks from prompts | +| **Market Researcher** | AI-powered market research and analysis | + +## Features + +### Plan-First Workflow (v1.3.0) +- AI generates a structured plan (architecture, tech stack, files, steps) before any code +- Plan Review Card with **Modify Plan**, **Start Coding**, and **Skip to Code** actions +- After code generation: **Preview** canvas + **Request Modifications** buttons +- Streaming plan mode with real-time parsing and canvas suppression + +### Multi-Provider AI (4 Providers) +| Provider | Auth | Models | +|----------|------|--------| +| **Qwen Code** | OAuth (2,000 free req/day) | Qwen Coder models | +| **Ollama Cloud** | API Key | Open-source models | +| **Z.AI Plan** | API Key | GLM general + coding models | +| **OpenRouter** | API Key | 20+ models (Gemini, Llama, Mistral, etc.) | + +### Visual Canvas +- Live code rendering with `[PREVIEW]` tags +- HTML, React, Python, and more — rendered in-browser +- Auto-detect renderable vs. code-only previews +- Responsive preview with device size selector (Full / Desktop / Tablet / Mobile) + +### Code Review & Web Search +- **Review Code** — Send generated code back to AI for bug/security/performance review +- **Web Search Grounding** — Toggle to enrich prompts with live web search results via SearXNG + +### Enhanced Prompt Engine +- 9 strategies: clarify, add-context, add-constraints, structure, add-examples, set-tone, expand, simplify, chain-of-thought +- Context-aware strategy selection based on detected intent +- 11+ intent detection patterns (coding, creative, analysis, etc.) + +### Other +- Multi-language support (English, Russian, Hebrew) +- Download generated artifacts as ZIP +- Push to GitHub integration +- Resilient multi-tier provider fallbacks + +## Quick Start + +1. **Clone & Install**: + ```bash + git clone https://github.rommark.dev/admin/PromptArch.git + cd PromptArch + npm install + ``` + +2. **Configuration**: + Copy `.env.example` to `.env` and add your API keys: + ```bash + cp .env.example .env + ``` + + Configure at least one provider: + - **Qwen**: Get OAuth credentials from [qwen.ai](https://qwen.ai) + - **Ollama**: Get API key from [ollama.com/cloud](https://ollama.com/cloud) + - **Z.AI**: Get API key from [docs.z.ai](https://docs.z.ai) + - **OpenRouter**: Get API key from [openrouter.ai/keys](https://openrouter.ai/keys) (free tier available) + +3. **Launch**: + ```bash + npm run dev + ``` + +4. Open [http://localhost:3000](http://localhost:3000) to begin. + +## Tech Stack + +- **Framework**: Next.js 15 (App Router, Turbopack) +- **Styling**: Tailwind CSS +- **State Management**: Zustand +- **Components**: shadcn/ui (Radix UI) +- **Icons**: Lucide React +- **Markdown**: react-markdown +- **Language**: TypeScript + +## Project Structure + +``` +promptarch/ + components/ + AIAssist.tsx # Main AI chat with plan-first workflow (1453 lines) + PromptEnhancer.tsx # Prompt enhancement UI with intent detection (556 lines) + SettingsPanel.tsx # Provider configuration and API key management (569 lines) + Sidebar.tsx # Navigation sidebar + GoogleAdsGenerator.tsx # Google Ads campaign generator + PRDGenerator.tsx # Product Requirements Document generator + ActionPlanGenerator.tsx # Action plan decomposition + SlidesGenerator.tsx # Presentation deck generator + MarketResearcher.tsx # Market research tool + HistoryPanel.tsx # Chat history management + lib/ + enhance-engine.ts # Modular prompt enhancement (9 strategies) + store.ts # Zustand state store + artifact-utils.ts # Preview/rendering utilities + export-utils.ts # Export to XLSX/HTML/ZIP + services/ + qwen-oauth.ts # Qwen OAuth streaming service + ollama-cloud.ts # Ollama Cloud streaming service + zai-plan.ts # Z.AI Plan streaming service + openrouter.ts # OpenRouter streaming service + model-adapter.ts # Unified provider adapter + adapter-instance.ts # Provider registry + i18n/ + translations.ts # EN/RU/HE translations + types/ + index.ts # TypeScript interfaces +``` + +## Versioning + +This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). See [CHANGELOG.md](CHANGELOG.md) for detailed release notes. + +| Version | Date | Highlights | +|---------|------|------------| +| [1.4.0](CHANGELOG.md#140---2026-03-18) | 2026-03-18 19:57 | Review Code button, web search grounding, responsive preview, model selector fix | +| [1.3.0](CHANGELOG.md#130---2026-03-18) | 2026-03-18 18:51 | Plan-first workflow, OpenRouter, post-coding UX, enhanced prompt engine | +| [1.2.0](CHANGELOG.md#120---2026-01-19) | 2026-01-19 19:16 | SEO agent fixes, Z.AI API validation | +| [1.1.0](CHANGELOG.md#110---2025-12-29) | 2025-12-29 17:55 | GitHub push, XLSX/HTML export, OAuth management | +| [1.0.0](CHANGELOG.md#100---2025-12-29) | 2025-12-29 13:51 | Initial release | + +## Development + +```bash +npm install # Install dependencies +npm run dev # Development server (Turbopack) +npm run build # Production build +npm start # Start production server +npm run lint # Lint code +``` + +## Attribution & Credits + +**Author**: Roman | RyzenAdvanced +- **Gitea**: [admin/PromptArch](https://github.rommark.dev/admin/PromptArch) +- **Telegram**: [@VibeCodePrompterSystem](https://t.me/VibeCodePrompterSystem) + +**Forked from**: [ClavixDev/Clavix](https://github.com/ClavixDev/Clavix) +- Visual and architectural evolution of the Clavix framework + +**Development Platform**: [TRAE.AI IDE](https://trae.ai) powered by [GLM 4.7](https://z.ai/subscribe?ic=R0K78RJKNW) + +## License + +ISC + +## Contributing + +Contributions are welcome! Please feel free to submit a Pull Request. diff --git a/app/api/fetch-url/route.ts b/app/api/fetch-url/route.ts new file mode 100644 index 0000000..9e95153 --- /dev/null +++ b/app/api/fetch-url/route.ts @@ -0,0 +1,117 @@ +/** + * Next.js API route: Fetch URL content for SEO/web auditing. + * Endpoint: GET /api/fetch-url?url=https://example.com + * Returns: { title, meta, headings, text, links, status } + */ + +import { NextRequest, NextResponse } from "next/server"; + +export async function GET(request: NextRequest) { + const targetUrl = request.nextUrl.searchParams.get("url"); + + if (!targetUrl) { + return NextResponse.json({ error: "URL parameter required" }, { status: 400 }); + } + + try { + new URL(targetUrl); + } catch { + return NextResponse.json({ error: "Invalid URL" }, { status: 400 }); + } + + try { + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), 12000); + + const res = await fetch(targetUrl, { + signal: controller.signal, + headers: { + "User-Agent": "PromptArch-SEO-Bot/1.5 (https://rommark.dev)", + Accept: "text/html,application/xhtml+xml,text/plain;q=0.9", + }, + }); + clearTimeout(timeout); + + if (!res.ok) { + return NextResponse.json({ error: `HTTP ${res.status}`, status: res.status }); + } + + const html = await res.text(); + + const titleMatch = html.match(/]*>([\s\S]*?)<\/title>/i); + const title = titleMatch ? titleMatch[1].trim() : ""; + + const descMatch = html.match(/]*name\s*=\s*["']description["'][^>]*content\s*=\s*["']([\s\S]*?)["']/i) + || html.match(/]*content\s*=\s*["']([\s\S]*?)["'][^>]*name\s*=\s*["']description["']/i); + const metaDescription = descMatch ? descMatch[1].trim() : ""; + + const kwMatch = html.match(/]*name\s*=\s*["']keywords["'][^>]*content\s*=\s*["']([\s\S]*?)["']/i) + || html.match(/]*content\s*=\s*["']([\s\S]*?)["'][^>]*name\s*=\s*["']keywords["']/i); + const metaKeywords = kwMatch ? kwMatch[1].trim() : ""; + + const headings: { level: number; text: string }[] = []; + const headingRegex = /]*>([\s\S]*?)<\/h[1-6]>/gi; + let hMatch; + while ((hMatch = headingRegex.exec(html)) !== null) { + const text = hMatch[2].replace(/<[^>]*>/g, "").trim(); + if (text) headings.push({ level: parseInt(hMatch[1]), text }); + } + + const links: { href: string; text: string; internal: boolean }[] = []; + const linkRegex = /]*href\s*=\s*["']([^"']*)["'][^>]*>([\s\S]*?)<\/a>/gi; + let lMatch; + const baseDomain = new URL(targetUrl).hostname; + while ((lMatch = linkRegex.exec(html)) !== null) { + const href = lMatch[1].trim(); + const text = lMatch[2].replace(/<[^>]*>/g, "").trim().substring(0, 100); + if (!href || href.startsWith("#") || href.startsWith("javascript:")) continue; + try { + const linkDomain = new URL(href, targetUrl).hostname; + links.push({ href, text, internal: linkDomain === baseDomain }); + } catch { continue; } + } + + const images: { src: string; alt: string }[] = []; + const imgRegex = /]*src\s*=\s*["']([^"']*)["'][^>]*alt\s*=\s*["']([^"']*)["'][^>]*\/?>/gi; + let iMatch; + while ((iMatch = imgRegex.exec(html)) !== null) { + images.push({ src: iMatch[1], alt: iMatch[2] }); + } + + const plainText = html + .replace(//gi, "") + .replace(//gi, "") + .replace(/<[^>]*>/g, " ") + .replace(/\s+/g, " ") + .trim() + .substring(0, 5000); + + const canonicalMatch = html.match(/]*rel\s*=\s*["']canonical["'][^>]*href\s*=\s*["']([^"']*)["']/i); + const canonical = canonicalMatch ? canonicalMatch[1] : ""; + + const ogTitleMatch = html.match(/]*property\s*=\s*["']og:title["'][^>]*content\s*=\s*["']([\s\S]*?)["']/i); + const ogTitle = ogTitleMatch ? ogTitleMatch[1].trim() : ""; + + const ogDescMatch = html.match(/]*property\s*=\s*["']og:description["'][^>]*content\s*=\s*["']([\s\S]*?)["']/i); + const ogDescription = ogDescMatch ? ogDescMatch[1].trim() : ""; + + return NextResponse.json({ + url: targetUrl, + title, + metaDescription, + metaKeywords, + canonical, + ogTitle, + ogDescription, + headings, + links: links.slice(0, 100), + images: images.slice(0, 50), + text: plainText, + htmlLength: html.length, + status: res.status, + }); + } catch (error) { + const msg = error instanceof Error ? error.message : "Fetch failed"; + return NextResponse.json({ error: msg }, { status: 500 }); + } +} diff --git a/components/AIAssist.tsx b/components/AIAssist.tsx index 049e66a..197238e 100644 --- a/components/AIAssist.tsx +++ b/components/AIAssist.tsx @@ -361,7 +361,7 @@ function parseStreamingContent(text: string, currentAgent: string) { // 3. Clean display text - hide all tag-like sequences and their partials chatDisplay = text // Hide complete tags (flexible brackets), including SUGGEST_AGENT - .replace(/\[+(?:AGENT|SUGGEST_AGENT|content|seo|smm|pm|code|design|web|app|PREVIEW|APP|WEB|SEO|CODE|DESIGN|SMM|PM|CONTENT|PREV):?[\w-]*:?[\w-]*\]+/gi, "") + .replace(/\[+(?:AGENT|SUGGEST_AGENT|content|seo|smm|pm|code|design|web|app|PREVIEW|APP|WEB|SEO|CODE|DESIGN|SMM|PM|CONTENT|PREV|WEB_AUDIT|WEB_SEARCH):?[\w-]*:?https?:\/\/[^\]]*\]+/gi, "").replace(/\[+(?:AGENT|SUGGEST_AGENT|content|seo|smm|pm|code|design|web|app|PREVIEW|APP|WEB|SEO|CODE|DESIGN|SMM|PM|CONTENT|PREV|WEB_AUDIT|WEB_SEARCH):?[\w-]*:?[\w-]*\]+/gi, "") // Hide content inside preview block (cleanly) .replace(/\[+PREVIEW:[\w-]+:?[\w-]+?\]+[\s\S]*?(?:\[\/(?:PREVIEW|APP|WEB|SEO|CODE|DESIGN|SMM|PM|CONTENT)\]+|$)/gi, "") // Hide closing tags @@ -695,7 +695,66 @@ export default function AIAssist() { setStatus(null); } - const response = await modelAdapter.generateAIAssistStream( + // SEO mode: auto-fetch URLs from user input for live auditing + if (currentAgent === "seo") { + const urlMatches = [...finalInput.matchAll(/https?:\/\/[^\s<>"')\]]+/gi)].map(m => m[0]); + const uniqueUrls = [...new Set(urlMatches)].slice(0, 2); + if (uniqueUrls.length > 0) { + setStatus("Auditing website" + (uniqueUrls.length > 1 ? "s" : "") + "..."); + try { + for (const url of uniqueUrls) { + const auditRes = await fetch("/api/fetch-url?url=" + encodeURIComponent(url)); + if (auditRes.ok) { + const auditData = await auditRes.json(); + enrichedInput += "\n\n[WEBSITE AUDIT DATA - " + url + "]\n"; + enrichedInput += "Title: " + (auditData.title || "N/A") + "\n"; + enrichedInput += "Meta Description: " + (auditData.metaDescription || "N/A") + "\n"; + enrichedInput += "Meta Keywords: " + (auditData.metaKeywords || "N/A") + "\n"; + enrichedInput += "Canonical: " + (auditData.canonical || "N/A") + "\n"; + enrichedInput += "OG Title: " + (auditData.ogTitle || "N/A") + "\n"; + enrichedInput += "OG Description: " + (auditData.ogDescription || "N/A") + "\n"; + enrichedInput += "Headings:\n"; + if (auditData.headings && auditData.headings.length > 0) { + for (const h of auditData.headings) { + enrichedInput += " H" + h.level + ": " + h.text + "\n"; + } + } else { + enrichedInput += " None found\n"; + } + const internalLinks = (auditData.links || []).filter((l: { internal: boolean }) => l.internal); + const externalLinks = (auditData.links || []).filter((l: { internal: boolean }) => !l.internal); + enrichedInput += "Links: " + internalLinks.length + " internal, " + externalLinks.length + " external (of " + (auditData.links || []).length + " total)\n"; + const imagesWithAlt = (auditData.images || []).filter((img: { alt: string }) => img.alt && img.alt.trim()); + const imagesNoAlt = (auditData.images || []).filter((img: { alt: string }) => !img.alt || !img.alt.trim()); + enrichedInput += "Images: " + (auditData.images || []).length + " total, " + imagesWithAlt.length + " with alt, " + imagesNoAlt.length + " without alt\n"; + enrichedInput += "Text content length: " + (auditData.text || "").length + " chars\n"; + enrichedInput += "HTML size: " + (auditData.htmlLength || 0) + " chars\n"; + enrichedInput += "[/WEBSITE AUDIT DATA]\n"; + } + } + } catch (e) { console.warn("Website audit failed:", e); } + setStatus(null); + } + // If no URL found and web search not enabled, auto-enable web search for SEO + if (uniqueUrls.length === 0 && !webSearchEnabled) { + try { + setStatus("Searching for SEO context..."); + const searchRes = await fetch("/api/search?q=" + encodeURIComponent(finalInput.split("\n")[0].substring(0, 200))); + if (searchRes.ok) { + const searchData = await searchRes.json(); + if (searchData.results && searchData.results.length > 0) { + const searchContext = searchData.results.slice(0, 5).map((r: { title: string; url: string; snippet: string }, i: number) => + (i + 1) + ". **" + r.title + "** (" + r.url + ") - " + r.snippet + ).join("\n"); + enrichedInput = "[WEB SEARCH CONTEXT - Top 5 relevant results]\n" + searchContext + "\n\n---\nUsing the above search results as reference context, answer the user query. Cite sources when relevant.\n\nUser query: " + finalInput; + } + } + } catch (e) { console.warn("SEO web search failed:", e); } + setStatus(null); + } + } + + const response = await modelAdapter.generateAIAssistStream( { messages: [...formattedHistory, { role: "user" as const, content: enrichedInput, timestamp: new Date() }], currentAgent, diff --git a/fix_device_array.py b/fix_device_array.py new file mode 100644 index 0000000..05d13c6 --- /dev/null +++ b/fix_device_array.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 +fp = '/home/uroma/promptarch/components/AIAssist.tsx' +with open(fp, 'r') as f: + content = f.read() + +# Fix the array that lost all its quotes +old = '{([[full, Full], [desktop, Desktop], [tablet, Tablet], [mobile, Mobile]] as const).map(([size, label]) => (' +new = '{([["full", "Full"], ["desktop", "Desktop"], ["tablet", "Tablet"], ["mobile", "Mobile"]] as const).map(([size, label]) => (' + +if old in content: + content = content.replace(old, new, 1) + print('Fixed array quotes') +else: + print('WARNING: Could not find array') + +with open(fp, 'w') as f: + f.write(content) diff --git a/fix_device_buttons.py b/fix_device_buttons.py new file mode 100644 index 0000000..650d691 --- /dev/null +++ b/fix_device_buttons.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +fp = '/home/uroma/promptarch/components/AIAssist.tsx' +with open(fp, 'r') as f: + content = f.read() + +changes = 0 + +# Fix 1: viewMode === preview -> viewMode === "preview" +old = 'viewMode === preview && (' +new = 'viewMode === "preview" && (' +if old in content: + content = content.replace(old, new, 1) + changes += 1 + print('Fix 1: viewMode quote restored') + +# Fix 2: className=flex -> className="flex" +old = 'className=flex items-center gap-1 mt-1.5' +new = 'className="flex items-center gap-1 mt-1.5"' +if old in content: + content = content.replace(old, new, 1) + changes += 1 + print('Fix 2: className quote restored') + +# Fix 3: Restore quotes in the device button className +# The issue is the className prop lost its opening quote and the string content lost quotes +old_btn_class = '''className={cn( + px-2 py-1 text-[9px] font-black uppercase rounded-md transition-all border, + deviceSize === size + ? bg-blue-500 text-white border-blue-500 shadow-md + : text-blue-300/50 border-transparent hover:text-blue-200 hover:bg-blue-900/30 + )}''' +new_btn_class = '''className={cn( + "px-2 py-1 text-[9px] font-black uppercase rounded-md transition-all border", + deviceSize === size + ? "bg-blue-500 text-white border-blue-500 shadow-md" + : "text-blue-300/50 border-transparent hover:text-blue-200 hover:bg-blue-900/30" + )}''' +if old_btn_class in content: + content = content.replace(old_btn_class, new_btn_class, 1) + changes += 1 + print('Fix 3: Button className quotes restored') + +with open(fp, 'w') as f: + f.write(content) + +print(f'Applied {changes}/3 fixes') diff --git a/fix_device_size.py b/fix_device_size.py new file mode 100644 index 0000000..182d6b4 --- /dev/null +++ b/fix_device_size.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +fp = '/home/uroma/promptarch/components/AIAssist.tsx' +with open(fp, 'r') as f: + lines = f.readlines() + +changes = 0 + +# CHANGE 1: Add deviceSize state after viewMode state +for i, line in enumerate(lines): + if 'const [viewMode, setViewMode]' in line and 'useState' in line: + new_lines = [ + line, + ' const [deviceSize, setDeviceSize] = useState<"full" | "desktop" | "tablet" | "mobile">("full");\n', + ' const deviceWidths: Record = { full: "100%", desktop: "1280px", tablet: "768px", mobile: "375px" };\n', + ] + lines[i:i+1] = new_lines + changes += 1 + print('Change 1: Added deviceSize state') + break + +# CHANGE 2: Find canvas wrapper and add device-size wrapper around LiveCanvas +for i, line in enumerate(lines): + if 'flex-1 overflow-auto relative bg-[#050505]' in line and i > 1400: + print('Found canvas wrapper at line', i+1) + # Find LiveCanvas line + for j in range(i, min(i+10, len(lines))): + if '\n' + lines[j:j] = [wrapper] + changes += 1 + print('Change 2: Added device wrapper before LiveCanvas') + break + break + +with open(fp, 'w') as f: + f.writelines(lines) + +print('Applied', changes, 'changes') diff --git a/fix_device_size2.py b/fix_device_size2.py new file mode 100644 index 0000000..d25f829 --- /dev/null +++ b/fix_device_size2.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +fp = '/home/uroma/promptarch/components/AIAssist.tsx' +with open(fp, 'r') as f: + lines = f.readlines() + +changes = 0 + +for i, line in enumerate(lines): + if 'flex-1 overflow-hidden relative' in line and i > 1400: + lines[i] = '
\n' + changes += 1 + print('Fixed overflow at line', i+1) + + for j in range(i, min(i+10, len(lines))): + if '\n' + lines[j:j] = [w] + changes += 1 + print('Added device wrapper before LiveCanvas at line', j+1) + break + break + +with open(fp, 'w') as f: + f.writelines(lines) + +print('Applied', changes, 'changes') diff --git a/fix_reviewcode.py b/fix_reviewcode.py new file mode 100644 index 0000000..a6a6619 --- /dev/null +++ b/fix_reviewcode.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +"""Fix the broken reviewCode template literal.""" + +fp = '/home/uroma/promptarch/components/AIAssist.tsx' +with open(fp, 'r') as f: + content = f.read() + +# Find and replace the broken reviewPrompt line +# The problem: backticks inside template literal need to be escaped with \` +old_line = ' const reviewPrompt = `Please review this generated code for bugs, security issues, performance problems, and best practices. Provide specific improvements:\\n\\n\\\\`\\\\`\\\\`${previewData.language || "code"}\\n${previewData.data}\\n\\\\`\\\\`\\\\`';' + +new_line = ' const reviewPrompt = "Please review this generated code for bugs, security issues, performance problems, and best practices. Provide specific improvements:\\n\\n\`\`\`" + (previewData.language || "code") + "\\n" + previewData.data + "\\n\`\`\`";' + +if old_line in content: + content = content.replace(old_line, new_line, 1) + print("Fixed reviewCode template literal") +else: + # Try with the actual escaped content + # Let's just find it by the function start and replace the whole function + print("Trying line-by-line approach...") + lines = content.split('\n') + for i, line in enumerate(lines): + if 'const reviewPrompt' in line and 'review this generated code' in line: + print(f"Found at line {i+1}: {line[:80]}...") + lines[i] = new_line + print("Fixed") + break + content = '\n'.join(lines) + +with open(fp, 'w') as f: + f.write(content) diff --git a/fix_reviewcode2.py b/fix_reviewcode2.py new file mode 100644 index 0000000..2e6dae9 --- /dev/null +++ b/fix_reviewcode2.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +fp = '/home/uroma/promptarch/components/AIAssist.tsx' +with open(fp, 'r') as f: + lines = f.readlines() + +bt = chr(96) # backtick character +nl = chr(92) + 'n' # \n + +for i, line in enumerate(lines): + if 'const reviewPrompt' in line and 'review this generated code' in line: + new_line = ' const reviewPrompt = "Please review this generated code for bugs, security issues, performance problems, and best practices. Provide specific improvements:" + "' + nl + '" + "' + nl + '" + "' + bt*3 + '" + (previewData.language || "code") + "' + nl + '" + previewData.data + "' + nl + '" + "' + bt*3 + '";\n' + lines[i] = new_line + print(f'Fixed line {i+1}') + print(repr(new_line)) + break + +with open(fp, 'w') as f: + f.writelines(lines) diff --git a/fix_v1.4.0.py b/fix_v1.4.0.py new file mode 100644 index 0000000..5cd144f --- /dev/null +++ b/fix_v1.4.0.py @@ -0,0 +1,210 @@ +#!/usr/bin/env python3 +"""Apply v1.4.0 improvements: model color fix, review button, web search grounding.""" + +import re + +fp = '/home/uroma/promptarch/components/AIAssist.tsx' +with open(fp, 'r') as f: + content = f.read() + +changes = 0 + +# ============================================================ +# CHANGE 1: Fix model selector text color +# ============================================================ +old_option = '{availableModels.map(m => )}' +new_option = '{availableModels.map(m => )}' + +if old_option in content: + content = content.replace(old_option, new_option, 1) + changes += 1 + print("Change 1: Fixed