Compare commits
3 Commits
6faca1c4b9
...
12ceb6594d
13
CHANGELOG.md
13
CHANGELOG.md
@@ -4,6 +4,19 @@ 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/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning]
|
and this project adheres to [Semantic Versioning]
|
||||||
|
## [2.2.1] - 2026-03-19 05:24 UTC
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- **Leads Canvas Preview** - Leads Finder now renders results as an Excel-like HTML table in the canvas, with columns: #, Name, Platform, Followers, Region, Bio, Link
|
||||||
|
- **Dark-Themed Leads Report** - Beautiful dark UI with emerald accents, stats grid (total leads, combined reach, top platform, top region), platform-colored badges (Instagram, Twitter, LinkedIn, YouTube, TikTok), and hover effects
|
||||||
|
- **Auto Canvas** - Leads Finder is now a visual agent that auto-opens the canvas when preview data is available
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- **Build Error** - Restored `<Badge variant="outline">` for plan card tech stack divs that were incorrectly replaced with plain `<div>` by an over-broad fix script
|
||||||
|
|
||||||
|
### Technical Details
|
||||||
|
- Files modified: 2 (AIAssist.tsx, openrouter.ts)
|
||||||
|
|
||||||
## [2.2.0] - 2026-03-19 04:44 UTC
|
## [2.2.0] - 2026-03-19 04:44 UTC
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# PromptArch: AI Orchestration Platform
|
# PromptArch: AI Orchestration Platform
|
||||||
|
|
||||||
> **Latest Version**: [v2.2.0](CHANGELOG.md#2.2.0---2026-03-19) (2026-03-19)(CHANGELOG.md#2.1.0---2026-03-18) (2026-03-18)(CHANGELOG.md#2.0.1---2026-03-18) (2026-03-18)(CHANGELOG.md#2.0.0---2026-03-18) (2026-03-18)(CHANGELOG.md#190---2026-03-18) (2026-03-18)
|
> **Latest Version**: [v2.2.1](CHANGELOG.md#2.2.1---2026-03-19) (2026-03-19)(CHANGELOG.md#2.1.0---2026-03-18) (2026-03-18)(CHANGELOG.md#2.0.1---2026-03-18) (2026-03-18)(CHANGELOG.md#2.0.0---2026-03-18) (2026-03-18)(CHANGELOG.md#190---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).
|
> **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).**
|
> **Learn more about this architecture [here](https://z.ai/subscribe?ic=R0K78RJKNW).**
|
||||||
|
|||||||
@@ -579,7 +579,7 @@ export default function AIAssist({ vibeMode = false }: { vibeMode?: boolean } =
|
|||||||
/module\.exports/i.test(preview.data);
|
/module\.exports/i.test(preview.data);
|
||||||
|
|
||||||
// Client-side detection
|
// Client-side detection
|
||||||
const isUI = ["web", "app", "design", "html", "ui"].includes(preview.type);
|
const isUI = ["web", "app", "design", "html", "ui", "leads"].includes(preview.type);
|
||||||
const hasTags = /<[a-z][\s\S]*>/i.test(preview.data);
|
const hasTags = /<[a-z][\s\S]*>/i.test(preview.data);
|
||||||
|
|
||||||
return (isUI || hasTags || preview.language === "html") && !isBackend;
|
return (isUI || hasTags || preview.language === "html") && !isBackend;
|
||||||
@@ -647,7 +647,7 @@ export default function AIAssist({ vibeMode = false }: { vibeMode?: boolean } =
|
|||||||
const isCodeAgent = currentAgent === "code";
|
const isCodeAgent = currentAgent === "code";
|
||||||
const wasIdle = !isApproval && isCodeAgent && (assistStep === "idle" || assistStep === "plan");
|
const wasIdle = !isApproval && isCodeAgent && (assistStep === "idle" || assistStep === "plan");
|
||||||
// Detect if user is modifying an existing visual artifact (not text-only agents like SEO/content)
|
// Detect if user is modifying an existing visual artifact (not text-only agents like SEO/content)
|
||||||
const isVisualAgent = currentAgent === "code" || currentAgent === "web" || currentAgent === "app" || currentAgent === "design" || currentAgent === "general";
|
const isVisualAgent = currentAgent === "code" || currentAgent === "web" || currentAgent === "app" || currentAgent === "design" || currentAgent === "general" || currentAgent === "leads";
|
||||||
if (assistStep === "preview" && isVisualAgent) setIsModifying(true);
|
if (assistStep === "preview" && isVisualAgent) setIsModifying(true);
|
||||||
setIsProcessing(true);
|
setIsProcessing(true);
|
||||||
if (assistStep === "idle" && isCodeAgent) setAssistStep("plan");
|
if (assistStep === "idle" && isCodeAgent) setAssistStep("plan");
|
||||||
@@ -1213,14 +1213,13 @@ export default function AIAssist({ vibeMode = false }: { vibeMode?: boolean } =
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex flex-wrap justify-center gap-2">
|
<div className="flex flex-wrap justify-center gap-2">
|
||||||
{["Forex traders in Singapore", "SaaS founders in UAE", "Fitness influencers on Instagram", "Crypto YouTubers in Latin America", "Marketing agencies in Southeast Asia"].map((label: string) => (
|
{["Forex traders in Singapore", "SaaS founders in UAE", "Fitness influencers on Instagram", "Crypto YouTubers in Latin America", "Marketing agencies in Southeast Asia"].map((label: string) => (
|
||||||
<Badge
|
<div
|
||||||
key={label}
|
key={label}
|
||||||
variant="secondary"
|
className="px-3 py-1.5 rounded-full cursor-pointer hover:bg-emerald-600 hover:text-white transition-all text-[10px] font-bold border border-black/20 text-black bg-white/90 shadow-sm"
|
||||||
className="px-3 py-1.5 rounded-full cursor-pointer hover:bg-emerald-600 hover:text-white transition-all text-[10px] font-bold border border-slate-600/30 text-slate-900 dark:text-white shadow-sm"
|
|
||||||
onClick={() => setInput(label)}
|
onClick={() => setInput(label)}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
</Badge>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1240,9 +1239,8 @@ export default function AIAssist({ vibeMode = false }: { vibeMode?: boolean } =
|
|||||||
</p>
|
</p>
|
||||||
<div className="mt-10 flex flex-wrap justify-center gap-3">
|
<div className="mt-10 flex flex-wrap justify-center gap-3">
|
||||||
{t.suggestions.map((chip: any) => (
|
{t.suggestions.map((chip: any) => (
|
||||||
<Badge
|
<div
|
||||||
key={chip.label}
|
key={chip.label}
|
||||||
variant="secondary"
|
|
||||||
className="px-4 py-2 rounded-full cursor-pointer hover:bg-blue-600 hover:text-white transition-all text-[11px] font-black border-transparent shadow-sm"
|
className="px-4 py-2 rounded-full cursor-pointer hover:bg-blue-600 hover:text-white transition-all text-[11px] font-black border-transparent shadow-sm"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setCurrentAgent(chip.agent);
|
setCurrentAgent(chip.agent);
|
||||||
@@ -1250,7 +1248,7 @@ export default function AIAssist({ vibeMode = false }: { vibeMode?: boolean } =
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{chip.label}
|
{chip.label}
|
||||||
</Badge>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1327,7 +1325,7 @@ export default function AIAssist({ vibeMode = false }: { vibeMode?: boolean } =
|
|||||||
<p className="text-[11px] font-bold text-slate-500 uppercase mb-1">{t.techStack}</p>
|
<p className="text-[11px] font-bold text-slate-500 uppercase mb-1">{t.techStack}</p>
|
||||||
<div className="flex flex-wrap gap-1">
|
<div className="flex flex-wrap gap-1">
|
||||||
{aiPlan.techStack?.map((t_stack: string) => (
|
{aiPlan.techStack?.map((t_stack: string) => (
|
||||||
<Badge key={t_stack} variant="outline" className="text-[9px] border-blue-500/30 text-blue-300 px-1.5 py-0">{t_stack}</Badge>
|
<Badge variant="outline" className="text-[9px] border-blue-500/30 text-blue-300 px-1.5 py-0">{t_stack}</Badge>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1367,7 +1365,6 @@ export default function AIAssist({ vibeMode = false }: { vibeMode?: boolean } =
|
|||||||
|
|
||||||
{msg.role === "assistant" && msg.preview && !(assistStep === "preview" && i === aiAssistHistory.length - 1 && !isProcessing) && (
|
{msg.role === "assistant" && msg.preview && !(assistStep === "preview" && i === aiAssistHistory.length - 1 && !isProcessing) && (
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
|
||||||
size="sm"
|
size="sm"
|
||||||
className="mt-5 w-full bg-blue-50 dark:bg-blue-900/30 border border-blue-200/60 dark:border-blue-800 text-blue-700 dark:text-blue-200 font-black uppercase tracking-[0.1em] text-[10px] rounded-2xl h-11 hover:scale-[1.02] active:scale-[0.98] transition-all"
|
className="mt-5 w-full bg-blue-50 dark:bg-blue-900/30 border border-blue-200/60 dark:border-blue-800 text-blue-700 dark:text-blue-200 font-black uppercase tracking-[0.1em] text-[10px] rounded-2xl h-11 hover:scale-[1.02] active:scale-[0.98] transition-all"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -1657,9 +1654,9 @@ export default function AIAssist({ vibeMode = false }: { vibeMode?: boolean } =
|
|||||||
{currentPreviewData?.isStreaming ? t.neuralLinkActive : t.syncComplete}
|
{currentPreviewData?.isStreaming ? t.neuralLinkActive : t.syncComplete}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<Badge variant="outline" className="text-[9px] border-blue-900 text-blue-200/50 font-black">
|
<div className="text-[9px] border-blue-900 text-blue-200/50 font-black">
|
||||||
{currentPreviewData?.language?.toUpperCase()} UTF-8
|
{currentPreviewData?.language?.toUpperCase()} UTF-8
|
||||||
</Badge>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -535,18 +535,63 @@ AGENTS & CAPABILITIES:
|
|||||||
- web: Frontend Developer. Build responsive sites. Use [PREVIEW:web:html]. Tailwind CSS CDN by default.
|
- web: Frontend Developer. Build responsive sites. Use [PREVIEW:web:html]. Tailwind CSS CDN by default.
|
||||||
- app: Mobile App Developer. Create mobile-first interfaces and dashboards. Use [PREVIEW:app:javascript].
|
- app: Mobile App Developer. Create mobile-first interfaces and dashboards. Use [PREVIEW:app:javascript].
|
||||||
- leads: Leads Finder. Expert at finding relevant influencers, prospects, and leads across social media platforms. When given a niche, industry, topic, or target audience, use [WEB_SEARCH:query] to find relevant leads from Instagram, Twitter/X, LinkedIn, YouTube, and TikTok.
|
- leads: Leads Finder. Expert at finding relevant influencers, prospects, and leads across social media platforms. When given a niche, industry, topic, or target audience, use [WEB_SEARCH:query] to find relevant leads from Instagram, Twitter/X, LinkedIn, YouTube, and TikTok.
|
||||||
**ALWAYS format each lead EXACTLY like this:**
|
**MUST wrap results in [PREVIEW:leads:html] so they render as a table in the Canvas.**
|
||||||
Name | Followers | Region | Location
|
|
||||||
One-line description of who they are and what they do.
|
**OUTPUT FORMAT:**
|
||||||
https://social-media-url/
|
Before [PREVIEW], give a brief chat summary (e.g. "Found 25 leads in forex across Singapore and UAE").
|
||||||
|
Then output the full table inside [PREVIEW:leads:html]...[/PREVIEW] using this HTML template:
|
||||||
|
|
||||||
|
<!DOCTYPE html><html><head><meta charset="utf-8"><style>
|
||||||
|
*{margin:0;padding:0;box-sizing:border-box}
|
||||||
|
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;background:#0a0f0f;color:#e2e8f0;padding:24px}
|
||||||
|
.header{text-align:center;margin-bottom:24px}
|
||||||
|
.header h1{font-size:24px;font-weight:800;background:linear-gradient(135deg,#10b981,#34d399);-webkit-background-clip:text;-webkit-text-fill-color:transparent}
|
||||||
|
.header p{color:#94a3b8;font-size:13px;margin-top:4px}
|
||||||
|
.stats{display:flex;gap:12px;margin-bottom:20px;flex-wrap:wrap}
|
||||||
|
.stat{background:rgba(16,185,129,0.08);border:1px solid rgba(16,185,129,0.15);border-radius:10px;padding:10px 16px;text-align:center;flex:1;min-width:100px}
|
||||||
|
.stat .num{font-size:20px;font-weight:800;color:#10b981}
|
||||||
|
.stat .lbl{font-size:10px;color:#94a3b8;text-transform:uppercase;letter-spacing:1px;margin-top:2px}
|
||||||
|
table{width:100%;border-collapse:collapse;background:rgba(15,23,42,0.6);border-radius:12px;overflow:hidden;border:1px solid rgba(148,163,184,0.1)}
|
||||||
|
thead th{background:rgba(16,185,129,0.12);color:#10b981;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:1.5px;padding:12px 14px;text-align:left;border-bottom:1px solid rgba(148,163,184,0.1);white-space:nowrap}
|
||||||
|
tbody tr{border-bottom:1px solid rgba(148,163,184,0.06);transition:background .2s}
|
||||||
|
tbody tr:hover{background:rgba(16,185,129,0.04)}
|
||||||
|
tbody td{padding:10px 14px;font-size:13px;color:#cbd5e1;border-bottom:1px solid rgba(148,163,184,0.04)}
|
||||||
|
.name{font-weight:700;color:#f1f5f9}
|
||||||
|
.url{color:#10b981;text-decoration:none;font-size:12px}
|
||||||
|
.url:hover{text-decoration:underline}
|
||||||
|
.badge{display:inline-block;padding:2px 8px;border-radius:20px;font-size:10px;font-weight:600}
|
||||||
|
.badge-instagram{background:rgba(225,48,108,0.15);color:#f472b6}
|
||||||
|
.badge-twitter{background:rgba(59,130,246,0.15);color:#60a5fa}
|
||||||
|
.badge-linkedin{background:rgba(59,130,246,0.15);color:#93c5fd}
|
||||||
|
.badge-youtube{background:rgba(239,68,68,0.15);color:#fca5a5}
|
||||||
|
.badge-tiktok{background:rgba(168,85,247,0.15);color:#c084fc}
|
||||||
|
.followers{color:#10b981;font-weight:700}
|
||||||
|
.region{color:#94a3b8;font-size:12px}
|
||||||
|
.bio{max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||||
|
@media(max-width:768px){table{font-size:11px}thead th,tbody td{padding:8px}.bio{max-width:120px}}
|
||||||
|
</style></head><body>
|
||||||
|
<div class="header"><h1>Leads Report</h1><p>Generated by PromptArch Leads Finder</p></div>
|
||||||
|
<div class="stats">
|
||||||
|
<div class="stat"><div class="num">TOTAL_LEADS_COUNT</div><div class="lbl">Total Leads</div></div>
|
||||||
|
<div class="stat"><div class="num">COMBINED_FOLLOWERS</div><div class="lbl">Combined Reach</div></div>
|
||||||
|
<div class="stat"><div class="num">TOP_PLATFORM</div><div class="lbl">Top Platform</div></div>
|
||||||
|
<div class="stat"><div class="num">TOP_REGION</div><div class="lbl">Top Region</div></div>
|
||||||
|
</div>
|
||||||
|
<table><thead><tr><th>#</th><th>Name</th><th>Platform</th><th>Followers</th><th>Region</th><th>Bio</th><th>Link</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<!-- Output one <tr> per lead: -->
|
||||||
|
<!-- <tr><td>1</td><td class="name">Name</td><td><span class="badge badge-PLATFORM">Platform</span></td><td class="followers">44.1K</td><td class="region">Region</td><td class="bio" title="Full bio">Brief description...</td><td><a class="url" href="URL" target="_blank">Visit Profile →</a></td></tr> -->
|
||||||
|
</tbody></table></body></html>
|
||||||
|
|
||||||
**RULES:**
|
**RULES:**
|
||||||
- Find 20+ leads per request unless user specifies a different number.
|
- Find 20+ leads per request unless user specifies a different number.
|
||||||
- Sort by relevance and follower count (most relevant first).
|
- Sort by relevance and follower count (most relevant first).
|
||||||
- Include the most prominent social media URL for each lead.
|
- Include the most prominent social media URL for each lead.
|
||||||
- Use exact follower counts when available (e.g. "44.1K", "275.6K", "1.2M").
|
- Use exact follower counts when available (e.g. "44.1K", "275.6K", "1.2M").
|
||||||
- Group by region when multiple regions are relevant.
|
- Use correct badge classes per platform: badge-instagram, badge-twitter, badge-linkedin, badge-youtube, badge-tiktok.
|
||||||
|
- Fill in the STATS div with actual counts from your results.
|
||||||
- Provide real, verifiable leads — never fabricate profiles or URLs.
|
- Provide real, verifiable leads — never fabricate profiles or URLs.
|
||||||
|
- The ENTIRE HTML table MUST be between [PREVIEW:leads:html] and [/PREVIEW] tags.
|
||||||
|
|
||||||
CANVAS MODE:
|
CANVAS MODE:
|
||||||
- When building, designing, or auditing, you MUST use the [PREVIEW] tag.
|
- When building, designing, or auditing, you MUST use the [PREVIEW] tag.
|
||||||
|
|||||||
Reference in New Issue
Block a user