chore: 清理
This commit is contained in:
@@ -1,434 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"><head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||
<title>Agent Park - Project Details</title>
|
||||
<script src="https://cdn.tailwindcss.com?plugins=forms,typography"></script>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Space+Mono:ital,wght@0,400;0,700;1,400&family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet"/>
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"/>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
darkMode: "class",
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: "#FFE100", // The vibrant yellow seen in headers and buttons
|
||||
"primary-dark": "#e5cb00",
|
||||
"background-light": "#F6F3EB", // Light beige background
|
||||
"background-dark": "#121212", // Dark mode background
|
||||
"surface-light": "#FFFFFF",
|
||||
"surface-dark": "#1E1E1E",
|
||||
"text-light": "#000000",
|
||||
"text-dark": "#E0E0E0",
|
||||
"border-light": "#000000",
|
||||
"border-dark": "#333333",
|
||||
},
|
||||
fontFamily: {
|
||||
display: ["Space Mono", "monospace"], // For headers and buttons
|
||||
body: ["Inter", "sans-serif"], // For body text
|
||||
},
|
||||
borderRadius: {
|
||||
DEFAULT: "0px", // Sharp corners generally seen in the design
|
||||
'md': "2px",
|
||||
},
|
||||
boxShadow: {
|
||||
'brutal': '4px 4px 0px 0px rgba(0,0,0,1)', // Brutalist shadow style
|
||||
'brutal-hover': '2px 2px 0px 0px rgba(0,0,0,1)',
|
||||
'brutal-dark': '4px 4px 0px 0px rgba(255,255,255,0.2)',
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style>::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: #cbd5e1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background-color: #94a3b8;
|
||||
}
|
||||
.dark ::-webkit-scrollbar-thumb {
|
||||
background-color: #475569;
|
||||
}.prose h2, .prose h3 {
|
||||
font-family: 'Space Mono', monospace;
|
||||
font-weight: 700;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-background-light dark:bg-background-dark text-text-light dark:text-text-dark font-body min-h-screen flex flex-col transition-colors duration-200">
|
||||
<div class="bg-primary text-black text-xs font-bold py-2 text-center uppercase tracking-widest border-b border-border-light dark:border-border-dark font-display">
|
||||
Discover the future of AI Agents <span class="material-icons text-sm align-middle ml-1">arrow_forward</span>
|
||||
</div>
|
||||
<nav class="border-b border-border-light dark:border-border-dark bg-background-light dark:bg-background-dark sticky top-0 z-50">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex justify-between items-center h-16">
|
||||
<div class="flex items-center">
|
||||
<a class="flex items-center gap-2 group" href="#">
|
||||
<span class="material-icons text-2xl group-hover:rotate-12 transition-transform">smart_toy</span>
|
||||
<span class="font-display font-bold text-lg tracking-tight">Agent Park</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="hidden md:flex items-center space-x-8">
|
||||
<a class="text-sm font-display font-bold hover:underline decoration-2 underline-offset-4" href="#">HOME</a>
|
||||
<a class="text-sm font-display font-bold hover:underline decoration-2 underline-offset-4" href="#">PROJECTS</a>
|
||||
<a class="text-sm font-display font-bold hover:underline decoration-2 underline-offset-4" href="#">BLOG</a>
|
||||
<a class="text-sm font-display font-bold hover:underline decoration-2 underline-offset-4" href="#">ABOUT</a>
|
||||
</div>
|
||||
<div class="hidden md:flex items-center gap-4">
|
||||
<div class="text-xs font-display font-bold border-r border-border-light dark:border-border-dark pr-4 mr-2">
|
||||
<span class="cursor-pointer hover:text-gray-600 dark:hover:text-gray-300">中文</span> / <span class="cursor-pointer hover:text-gray-600 dark:hover:text-gray-300">EN</span>
|
||||
</div>
|
||||
<a class="font-display text-xs font-bold uppercase border border-border-light dark:border-white px-4 py-2 hover:bg-black hover:text-white dark:hover:bg-white dark:hover:text-black transition-all shadow-[2px_2px_0px_0px_rgba(0,0,0,1)] dark:shadow-[2px_2px_0px_0px_rgba(255,255,255,1)] active:translate-x-[2px] active:translate-y-[2px] active:shadow-none" href="#">
|
||||
Submit Project
|
||||
</a>
|
||||
</div>
|
||||
<div class="md:hidden flex items-center">
|
||||
<button class="outline-none mobile-menu-button">
|
||||
<span class="material-icons">menu</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<main class="flex-grow container mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||
<div class="mb-8">
|
||||
<a class="inline-flex items-center text-sm font-display font-bold text-gray-500 hover:text-black dark:text-gray-400 dark:hover:text-white transition-colors group" href="#">
|
||||
<span class="material-icons text-base mr-1 group-hover:-translate-x-1 transition-transform">arrow_back</span>
|
||||
BACK TO PROJECTS
|
||||
</a>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 lg:grid-cols-12 gap-12">
|
||||
<div class="lg:col-span-8">
|
||||
<header class="mb-10 relative">
|
||||
<div class="absolute -top-10 -right-10 w-24 h-24 border border-black dark:border-white opacity-20 rounded-full hidden md:block" style="border-radius: 40% 60% 70% 30% / 40% 50% 60% 50%;"></div>
|
||||
<h1 class="font-display text-4xl md:text-6xl font-bold mb-6 leading-tight uppercase relative z-10">
|
||||
AutoGPT X
|
||||
</h1>
|
||||
<div class="flex flex-wrap items-center gap-4 text-sm font-mono text-gray-600 dark:text-gray-400 mb-8 pb-8 border-b border-gray-300 dark:border-gray-700">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="material-icons text-base">calendar_today</span>
|
||||
<span>Added Oct 24, 2023</span>
|
||||
</div>
|
||||
<span class="hidden sm:inline text-gray-300">|</span>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="material-icons text-base">category</span>
|
||||
<span>Autonomous Agent</span>
|
||||
</div>
|
||||
<span class="hidden sm:inline text-gray-300">|</span>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="material-icons text-base">code</span>
|
||||
<span>Open Source</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-3 mb-8">
|
||||
<span class="px-3 py-1 border border-black dark:border-gray-500 text-xs font-display font-bold uppercase bg-white dark:bg-gray-800">Python</span>
|
||||
<span class="px-3 py-1 border border-black dark:border-gray-500 text-xs font-display font-bold uppercase bg-white dark:bg-gray-800">LLM</span>
|
||||
<span class="px-3 py-1 border border-black dark:border-gray-500 text-xs font-display font-bold uppercase bg-white dark:bg-gray-800">Automation</span>
|
||||
<span class="px-3 py-1 border border-black dark:border-gray-500 text-xs font-display font-bold uppercase bg-white dark:bg-gray-800">GPT-4</span>
|
||||
</div>
|
||||
<div class="relative w-full aspect-video border-2 border-black dark:border-gray-600 bg-gray-100 dark:bg-gray-800 mb-10 overflow-hidden shadow-brutal dark:shadow-none">
|
||||
<img alt="AutoGPT X Interface Abstract Visualization" class="w-full h-full object-cover" src="https://lh3.googleusercontent.com/aida-public/AB6AXuAvvUwvvv9eQigRJYV_SkkRfdJYe8PSpnsqNqriFIrtYb3ZxrfwipLWMSn-m8oQB9oT1LuynQY8q6o3m_GOFZGK0yM2nLxapj0EbrWKj49NN3JdO6I65VMXvnlM56uRAHXh-JKoIaFFlQRUg0hlhLlc7Nc_UfniYNUpu_0CX6OPsJwYhIRaAMeqjgLuWTfLA6cKNtkixtbNr9K7AI5puEIJjPLs7tQuUC5_7NjEiFSbBPFg_pO95-buoa59aO4_Qafu600RkDE9lDQ"/>
|
||||
<div class="absolute bottom-4 right-4 bg-white dark:bg-black px-2 py-1 text-xs font-mono border border-black dark:border-gray-500">v2.0.1 Stable</div>
|
||||
</div>
|
||||
</header>
|
||||
<article class="prose prose-lg dark:prose-invert max-w-none prose-headings:font-display prose-a:text-blue-600 dark:prose-a:text-blue-400 hover:prose-a:text-blue-800 dark:hover:prose-a:text-blue-300 prose-img:border-2 prose-img:border-black dark:prose-img:border-gray-600 prose-img:shadow-brutal dark:prose-img:shadow-none">
|
||||
<p class="lead font-display text-xl mb-8">
|
||||
AutoGPT X is an experimental open-source application showcasing the capabilities of the GPT-4 language model. This program, driven by GPT-4, chains together LLM "thoughts", to autonomously achieve whatever goal you set.
|
||||
</p>
|
||||
<h2>Overview</h2>
|
||||
<p>
|
||||
Unlike typical AI chatbots that require constant prompting, AutoGPT X takes a single goal and breaks it down into sub-tasks. It utilizes the internet for searching and gathering information, manages long-term and short-term memory, and can execute code or scripts to accomplish complex workflows.
|
||||
</p>
|
||||
<p>
|
||||
As one of the first examples of GPT-4 running fully autonomously, AutoGPT X pushes the boundaries of what is possible with AI agents. It serves as a framework for building sophisticated AI assistants capable of performing real-world tasks with minimal human intervention.
|
||||
</p>
|
||||
<h3>Key Features</h3>
|
||||
<ul class="list-disc pl-6 space-y-2 marker:text-black dark:marker:text-white">
|
||||
<li><strong>Internet Access:</strong> Searches and gathers information autonomously.</li>
|
||||
<li><strong>Long-Term Memory:</strong> Retains context over extended sessions.</li>
|
||||
<li><strong>GPT-4 Powered:</strong> Leverages the reasoning capabilities of state-of-the-art LLMs.</li>
|
||||
<li><strong>File Management:</strong> Can read and write files to your local system.</li>
|
||||
<li><strong>Extensible:</strong> Plugin system allows for custom integrations.</li>
|
||||
</ul>
|
||||
<h3>Getting Started</h3>
|
||||
<p>
|
||||
To install AutoGPT X, you will need Python 3.10 or later. Clone the repository and install the dependencies:
|
||||
</p>
|
||||
<pre class="bg-gray-100 dark:bg-gray-800 border border-black dark:border-gray-600 p-4 font-mono text-sm overflow-x-auto"><code>git clone https://github.com/agentpark/autogpt-x.git
|
||||
cd autogpt-x
|
||||
pip install -r requirements.txt
|
||||
python main.py</code></pre>
|
||||
<blockquote>
|
||||
"The goal of AutoGPT X is to make GPT-4 fully autonomous."
|
||||
</blockquote>
|
||||
<h2>Use Cases</h2>
|
||||
<p>
|
||||
Developers and enthusiasts are using AutoGPT X for a variety of tasks, including:
|
||||
</p>
|
||||
<ul class="list-disc pl-6 space-y-2 marker:text-black dark:marker:text-white">
|
||||
<li>Automated market research and report generation.</li>
|
||||
<li>Code debugging and autonomous software development.</li>
|
||||
<li>Personal assistant tasks like booking flights or ordering food.</li>
|
||||
<li>Content creation and social media management.</li>
|
||||
</ul>
|
||||
</article>
|
||||
<div class="mt-12 pt-8 border-t border-gray-300 dark:border-gray-700 flex flex-col sm:flex-row justify-between items-center gap-6">
|
||||
<div class="flex gap-4">
|
||||
<button class="p-2 border border-black dark:border-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors" title="Share on X">
|
||||
<span class="material-icons text-lg">share</span>
|
||||
</button>
|
||||
<button class="p-2 border border-black dark:border-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors" title="Copy Link">
|
||||
<span class="material-icons text-lg">link</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-sm font-display font-bold text-gray-500">DID THIS AGENT FIX THIS?</span>
|
||||
<button class="px-4 py-2 bg-primary text-black font-display font-bold text-xs uppercase border border-black hover:bg-yellow-400 transition-colors shadow-[2px_2px_0px_0px_rgba(0,0,0,1)] active:shadow-none active:translate-x-[2px] active:translate-y-[2px]">Yes, it rocks</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<aside class="lg:col-span-4 space-y-8">
|
||||
<div class="bg-white dark:bg-surface-dark border-2 border-black dark:border-gray-600 p-6 shadow-brutal dark:shadow-brutal-dark">
|
||||
<h3 class="font-display font-bold text-lg mb-6 uppercase border-b-2 border-primary pb-2 inline-block">Project Links</h3>
|
||||
<div class="space-y-4">
|
||||
<a class="flex items-center justify-between group p-3 border border-gray-200 dark:border-gray-700 hover:border-black dark:hover:border-white transition-colors bg-gray-50 dark:bg-gray-800" href="#">
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="material-icons">language</span>
|
||||
<span class="font-bold text-sm">Official Website</span>
|
||||
</div>
|
||||
<span class="material-icons text-sm group-hover:translate-x-1 transition-transform">arrow_forward</span>
|
||||
</a>
|
||||
<a class="flex items-center justify-between group p-3 border border-gray-200 dark:border-gray-700 hover:border-black dark:hover:border-white transition-colors bg-gray-50 dark:bg-gray-800" href="#">
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="material-icons">code</span>
|
||||
<span class="font-bold text-sm">GitHub Repo</span>
|
||||
</div>
|
||||
<span class="material-icons text-sm group-hover:translate-x-1 transition-transform">arrow_forward</span>
|
||||
</a>
|
||||
<a class="flex items-center justify-between group p-3 border border-gray-200 dark:border-gray-700 hover:border-black dark:hover:border-white transition-colors bg-gray-50 dark:bg-gray-800" href="#">
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="material-icons">description</span>
|
||||
<span class="font-bold text-sm">Documentation</span>
|
||||
</div>
|
||||
<span class="material-icons text-sm group-hover:translate-x-1 transition-transform">arrow_forward</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="mt-8 pt-6 border-t border-gray-200 dark:border-gray-700">
|
||||
<!-- 方案A: GitHub 专用统计卡片 - 分离 GitHub 数据和其他元数据 -->
|
||||
<div class="mb-6">
|
||||
<div class="bg-gray-100 dark:bg-gray-800 border-2 border-gray-300 dark:border-gray-600 text-black dark:text-white p-4">
|
||||
<h3 class="font-display text-xs uppercase tracking-widest mb-3 flex items-center gap-2">
|
||||
<svg class="w-4 h-4 text-primary" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-3.14-.95-3.14-.95-.43-.92-.1-1.25-.1-1.25.2-.05.41.08.95.08 2.76 1.89 3.78 1.89 3.78 1.69 2.88 4.44 2.05 5.53-.16.47-.86-.94-1.25-1.14-.42-.26-.89-.04-1.25.23-.89.65-2.18.95-3.3 1.01-.22.01-.44.05-.66.12-.26.11-.53.03-.72-.13-.22-.18-.44-.49-.44-.49-.25-.95-.08-1.25.23-.72.72-1.87 2.05-2.84 2.85-.13.11-.24.26-.24.42 0 .33.27.76.76.76 1.16 0 .87.72 1.96 2.05 2.4 2.82.2.06.43.09.65.05.31-.06.6-.17.87-.33.26-.16.48-.36.63-.57.23-.21.47-.44.64-.67.19-.26.35-.54.48-.83.11-.26.17-.54.17-.82 0-.47-.27-.91-.66-1.1-.67-.34-1.45-.51-2.32-.51-.88 0-1.67.18-2.35.53-.26.13-.5.25-.73.36-.22.1-.42.23-.58.37-.14.13-.26.26-.34.4-.07.14-.1.29-.1.44 0 .18.09.34.25.46.13.11.29.18.46.18.19 0 .38-.06.55-.17.15-.11.28-.24.39-.39.1-.15.18-.31.23-.48.05-.18.06-.36.06-.54 0-.3-.17-.57-.44-.74-.23-.17-.5-.26-.78-.26-.28 0-.55.09-.79.26-.23.17-.41.39-.54.64-.12.24-.17.5-.17.77 0 .26.17.5.43.67.25.17.57.26.89.26.31 0 .6-.09.85-.26.23-.17.41-.39.54-.64.12-.24.18-.5.18-.77 0-.26-.17-.5-.43-.67-.26-.17-.57-.26-.89-.26-.31 0-.6.09-.85.26-.23.17-.41.39-.54.64-.12.24-.17.5-.17.77zM8 15c-3.86 0-7-3.14-7-7s3.14-7 7-7 7 3.14 7 7-3.14 7-7 7z"/>
|
||||
</svg>
|
||||
GitHub Statistics
|
||||
</h3>
|
||||
<!-- 使用 Shields.io 徽章网格显示所有 GitHub 实时数据 -->
|
||||
<div class="grid grid-cols-2 gap-3">
|
||||
<a href="https://github.com/agentpark/autogpt-x/stargazers" class="group" title="View stars on GitHub">
|
||||
<div class="flex items-center gap-2 hover:bg-white dark:hover:bg-black hover:bg-opacity-50 p-2 rounded transition-colors">
|
||||
<svg class="w-4 h-4 text-primary" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M8 .25a.75.75 0 01.673.418l1.882 3.815 4.21.612a.75.75 0 01.416 1.279l-3.046 2.97.719 4.192a.75.75 0 01-1.088.791L8 12.347l-3.766 1.98a.75.75 0 01-1.088-.79l.72-4.194L.818 6.374a.75.75 0 01.416-1.28l4.21-.611L7.327.668A.75.75 0 018 .25z"/>
|
||||
</svg>
|
||||
<div>
|
||||
<div class="text-[9px] uppercase font-mono text-gray-500">Stars</div>
|
||||
<div class="font-display font-bold text-lg">142k</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a href="https://github.com/agentpark/autogpt-x/network/members" class="group" title="View forks on GitHub">
|
||||
<div class="flex items-center gap-2 hover:bg-white dark:hover:bg-black hover:bg-opacity-50 p-2 rounded transition-colors">
|
||||
<svg class="w-4 h-4 text-blue-500" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M5 3.25a.75.75 0 11-1.5 0 .75.75 0 011.5 0zm0 2.122a2.25 2.25 0 10-1.5 0v.878A2.25 2.25 0 005.75 8.5h1.5v2.128a2.251 2.251 0 101.5 0V8.5h1.5a2.25 2.25 0 002.25-2.25v-.878a2.25 2.25 0 10-1.5 0v.878a.75.75 0 01-.75.75h-4.5A.75.75 0 015 6.25v-.878zm3.75 7.378a.75.75 0 11-1.5 0 .75.75 0 011.5 0zm3-8.75a.75.75 0 100-1.5.75.75 0 000 1.5z"/>
|
||||
</svg>
|
||||
<div>
|
||||
<div class="text-[9px] uppercase font-mono text-gray-500">Forks</div>
|
||||
<div class="font-display font-bold text-lg">34k</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a href="https://github.com/agentpark/autogpt-x/issues" class="group" title="View issues on GitHub">
|
||||
<div class="flex items-center gap-2 hover:bg-white dark:hover:bg-black hover:bg-opacity-50 p-2 rounded transition-colors">
|
||||
<svg class="w-4 h-4 text-green-600" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M8 9.5a1.5 1.5 0 100-3 1.5 1.5 0 000 3z"/>
|
||||
<path d="M8 0a8 8 0 100 16A8 8 0 008 0zM1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0z"/>
|
||||
</svg>
|
||||
<div>
|
||||
<div class="text-[9px] uppercase font-mono text-gray-500">Issues</div>
|
||||
<div class="font-display font-bold text-lg">892</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a href="https://github.com/agentpark/autogpt-x/blob/main/LICENSE" class="group" title="View license on GitHub">
|
||||
<div class="flex items-center gap-2 hover:bg-white dark:hover:bg-black hover:bg-opacity-50 p-2 rounded transition-colors">
|
||||
<svg class="w-4 h-4 text-purple-600" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M8 1.75c4.556 0 8.25 3.694 8.25 8.25 0 1.356-.344 2.647-.956 3.78-.556.057-1.072.25-1.444.525-.436.32-.688.742-.688 1.25 0 .469.253.891.688 1.25.47.4.869.496 1.444.525 2.09-.613 3.325-1.438 4.188-.47.48-1.088.79-1.5.79-.406-.006-.738-.274-.96-.638-.31-.494-.672-.59-1.031-.59-.25 0-.476.088-.656.25-.182.163-.39.25-.625.25-.238 0-.447-.087-.625-.25-.178-.164-.395-.25-.641-.25-.356 0-.722.096-1.031.59-.413.584-.554.29-1.5-.79-.612.313-1.156.48-1.625.525-.47-.22-.906-.25-1.444-.525-.612-1.133-.956-3.78-.956-4.556 0-8.25 3.694-8.25 8.25zM4.5 9a.5.5 0 01.5-.5h6a.5.5 0 010 1h-6a.5.5 0 01-.5-.5z"/>
|
||||
</svg>
|
||||
<div>
|
||||
<div class="text-[9px] uppercase font-mono text-gray-500">License</div>
|
||||
<div class="font-display font-bold text-lg">MIT</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="mt-3 pt-3 border-t border-gray-300 dark:border-gray-600">
|
||||
<div class="flex items-center justify-between text-xs font-mono">
|
||||
<span class="text-gray-500">Last commit</span>
|
||||
<span class="font-display font-bold">2 days ago</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-primary border-2 border-black p-6 relative overflow-hidden shadow-brutal dark:shadow-none group cursor-pointer hover:bg-yellow-400 transition-colors">
|
||||
<div class="absolute top-0 right-0 w-20 h-20 bg-white opacity-20 transform rotate-45 translate-x-10 -translate-y-10"></div>
|
||||
<div class="absolute bottom-0 left-0 w-16 h-16 bg-black opacity-10 rounded-full transform -translate-x-8 translate-y-8"></div>
|
||||
<div class="relative z-10 text-center">
|
||||
<div class="w-12 h-12 bg-white rounded-full border-2 border-black flex items-center justify-center mx-auto mb-4 group-hover:scale-110 transition-transform">
|
||||
<span class="material-icons text-2xl">rocket_launch</span>
|
||||
</div>
|
||||
<h3 class="font-display font-bold text-xl mb-2">Build Your Own Agent?</h3>
|
||||
<p class="text-sm font-medium mb-6">Start using our API to build custom agents in minutes.</p>
|
||||
<button class="w-full bg-black text-white font-display font-bold py-3 text-sm uppercase hover:bg-gray-800 transition-colors shadow-none">
|
||||
Get Started Now
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sticky top-24 bg-background-light dark:bg-background-dark border border-gray-300 dark:border-gray-700 p-6 hidden lg:block">
|
||||
<h3 class="font-display font-bold text-sm uppercase tracking-widest mb-4 text-gray-500 dark:text-gray-400">On this page</h3>
|
||||
<ul class="space-y-3 text-sm border-l-2 border-gray-200 dark:border-gray-700 pl-4">
|
||||
<li><a class="text-black dark:text-white font-bold border-l-2 border-black dark:border-white -ml-[18px] pl-4 block" href="#">Overview</a></li>
|
||||
<li><a class="text-gray-600 dark:text-gray-400 hover:text-black dark:hover:text-white transition-colors block" href="#">Key Features</a></li>
|
||||
<li><a class="text-gray-600 dark:text-gray-400 hover:text-black dark:hover:text-white transition-colors block" href="#">Getting Started</a></li>
|
||||
<li><a class="text-gray-600 dark:text-gray-400 hover:text-black dark:hover:text-white transition-colors block" href="#">Use Cases</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
<section class="mt-20 pt-12 border-t border-black dark:border-gray-700">
|
||||
<div class="flex justify-between items-end mb-8">
|
||||
<h2 class="font-display text-3xl font-bold uppercase">Related Projects</h2>
|
||||
<a class="font-display text-xs font-bold uppercase hover:underline flex items-center gap-1 group" href="#">
|
||||
View All <span class="material-icons text-sm group-hover:translate-x-1 transition-transform">arrow_forward</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div class="border-2 border-black dark:border-gray-600 p-6 bg-white dark:bg-surface-dark hover:shadow-brutal hover:-translate-y-1 transition-all duration-200 cursor-pointer flex flex-col h-full dark:hover:shadow-brutal-dark">
|
||||
<div class="flex justify-between items-start mb-4">
|
||||
<h3 class="font-display text-xl font-bold">BabyAGI</h3>
|
||||
<span class="material-icons text-gray-400">psychology</span>
|
||||
</div>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-300 mb-6 flex-grow line-clamp-3">
|
||||
Task-driven autonomous agent that uses OpenAI and Pinecone APIs to create, prioritize, and execute tasks.
|
||||
</p>
|
||||
<div class="flex gap-2 mb-6">
|
||||
<span class="text-[10px] uppercase font-bold border border-gray-300 dark:border-gray-600 px-2 py-1">Python</span>
|
||||
<span class="text-[10px] uppercase font-bold border border-gray-300 dark:border-gray-600 px-2 py-1">Task</span>
|
||||
</div>
|
||||
<div class="mt-auto pt-4 border-t border-gray-100 dark:border-gray-700">
|
||||
<span class="text-xs font-display font-bold uppercase flex items-center group">
|
||||
View Details <span class="material-icons text-sm ml-1 group-hover:translate-x-1 transition-transform">arrow_forward</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-2 border-black dark:border-gray-600 p-6 bg-white dark:bg-surface-dark hover:shadow-brutal hover:-translate-y-1 transition-all duration-200 cursor-pointer flex flex-col h-full dark:hover:shadow-brutal-dark">
|
||||
<div class="flex justify-between items-start mb-4">
|
||||
<h3 class="font-display text-xl font-bold">LangChain</h3>
|
||||
<span class="material-icons text-gray-400">link</span>
|
||||
</div>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-300 mb-6 flex-grow line-clamp-3">
|
||||
Building applications with LLMs through composability. The standard framework for chaining LLM capabilities.
|
||||
</p>
|
||||
<div class="flex gap-2 mb-6">
|
||||
<span class="text-[10px] uppercase font-bold border border-gray-300 dark:border-gray-600 px-2 py-1">Framework</span>
|
||||
<span class="text-[10px] uppercase font-bold border border-gray-300 dark:border-gray-600 px-2 py-1">Python</span>
|
||||
</div>
|
||||
<div class="mt-auto pt-4 border-t border-gray-100 dark:border-gray-700">
|
||||
<span class="text-xs font-display font-bold uppercase flex items-center group">
|
||||
View Details <span class="material-icons text-sm ml-1 group-hover:translate-x-1 transition-transform">arrow_forward</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-2 border-black dark:border-gray-600 p-6 bg-white dark:bg-surface-dark hover:shadow-brutal hover:-translate-y-1 transition-all duration-200 cursor-pointer flex flex-col h-full dark:hover:shadow-brutal-dark">
|
||||
<div class="flex justify-between items-start mb-4">
|
||||
<h3 class="font-display text-xl font-bold">GodMode</h3>
|
||||
<span class="material-icons text-gray-400">bolt</span>
|
||||
</div>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-300 mb-6 flex-grow line-clamp-3">
|
||||
A dedicated web platform to access the powers of AutoGPT and BabyAGI directly from your browser.
|
||||
</p>
|
||||
<div class="flex gap-2 mb-6">
|
||||
<span class="text-[10px] uppercase font-bold border border-gray-300 dark:border-gray-600 px-2 py-1">Web</span>
|
||||
<span class="text-[10px] uppercase font-bold border border-gray-300 dark:border-gray-600 px-2 py-1">UI</span>
|
||||
</div>
|
||||
<div class="mt-auto pt-4 border-t border-gray-100 dark:border-gray-700">
|
||||
<span class="text-xs font-display font-bold uppercase flex items-center group">
|
||||
View Details <span class="material-icons text-sm ml-1 group-hover:translate-x-1 transition-transform">arrow_forward</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<footer class="bg-background-light dark:bg-background-dark border-t border-border-light dark:border-border-dark py-12">
|
||||
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-12 mb-12">
|
||||
<div class="col-span-1 md:col-span-1">
|
||||
<a class="flex items-center gap-2 mb-4" href="#">
|
||||
<span class="material-icons text-2xl">smart_toy</span>
|
||||
<span class="font-display font-bold text-lg tracking-tight">Agent Park</span>
|
||||
</a>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">
|
||||
Discover and explore high-quality AI projects from across the web. Curated for developers and enthusiasts.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="font-display font-bold text-sm uppercase mb-4">Agent Park</h4>
|
||||
<ul class="space-y-2 text-sm text-gray-600 dark:text-gray-400">
|
||||
<li><a class="hover:text-black dark:hover:text-white" href="#">About Us</a></li>
|
||||
<li><a class="hover:text-black dark:hover:text-white" href="#">Contact</a></li>
|
||||
<li><a class="hover:text-black dark:hover:text-white" href="#">Careers</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="font-display font-bold text-sm uppercase mb-4">Resources</h4>
|
||||
<ul class="space-y-2 text-sm text-gray-600 dark:text-gray-400">
|
||||
<li><a class="hover:text-black dark:hover:text-white" href="#">Blog</a></li>
|
||||
<li><a class="hover:text-black dark:hover:text-white" href="#">Newsletter</a></li>
|
||||
<li><a class="hover:text-black dark:hover:text-white" href="#">Documentation</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="font-display font-bold text-sm uppercase mb-4">Follow Us</h4>
|
||||
<div class="flex gap-2">
|
||||
<a class="w-8 h-8 flex items-center justify-center border border-gray-400 hover:border-black dark:hover:border-white hover:bg-black hover:text-white dark:hover:bg-white dark:hover:text-black transition-colors font-display font-bold" href="#">X</a>
|
||||
<a class="w-8 h-8 flex items-center justify-center border border-gray-400 hover:border-black dark:hover:border-white hover:bg-black hover:text-white dark:hover:bg-white dark:hover:text-black transition-colors font-display font-bold" href="#">Li</a>
|
||||
<a class="w-8 h-8 flex items-center justify-center border border-gray-400 hover:border-black dark:hover:border-white hover:bg-black hover:text-white dark:hover:bg-white dark:hover:text-black transition-colors font-display font-bold" href="#">Gh</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-t border-gray-300 dark:border-gray-800 pt-8 flex flex-col md:flex-row justify-between items-center text-xs font-mono text-gray-500 uppercase">
|
||||
<p>© 2025 Agent Park. All rights reserved.</p>
|
||||
<p>Designed for AI Builders</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<script>
|
||||
// Simple mobile menu toggle
|
||||
const btn = document.querySelector("button.mobile-menu-button");
|
||||
const menu = document.querySelector(".mobile-menu");
|
||||
btn.addEventListener("click", () => {
|
||||
// In a real scenario, this would toggle a hidden mobile menu div
|
||||
alert("Mobile menu clicked (implementation simplified for this demo)");
|
||||
});
|
||||
</script>
|
||||
|
||||
</body></html>
|
||||
@@ -1,346 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"><head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||
<title>Agent Park Homepage</title>
|
||||
<script src="https://cdn.tailwindcss.com?plugins=forms,typography"></script>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Space+Mono:ital,wght@0,400;0,700;1,400&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet"/>
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"/>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
darkMode: "class",
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: "#FFD700", // Gold/Yellow from MotherDuck
|
||||
secondary: "#ff6f00", // Orange accent
|
||||
"background-light": "#F7F5F0", // Off-white beige from MotherDuck
|
||||
"background-dark": "#1a1a1a", // Dark charcoal for dark mode
|
||||
"surface-light": "#FFFFFF",
|
||||
"surface-dark": "#262626",
|
||||
"border-light": "#000000",
|
||||
"border-dark": "#4a4a4a",
|
||||
"text-light": "#000000",
|
||||
"text-dark": "#F7F5F0",
|
||||
},
|
||||
fontFamily: {
|
||||
display: ['"Space Mono"', "monospace"], // Monospace for headings like MotherDuck
|
||||
sans: ['"Inter"', "sans-serif"],
|
||||
},
|
||||
boxShadow: {
|
||||
'neobrutalism': '4px 4px 0px 0px rgba(0,0,0,1)',
|
||||
'neobrutalism-sm': '2px 2px 0px 0px rgba(0,0,0,1)',
|
||||
'neobrutalism-hover': '2px 2px 0px 0px rgba(0,0,0,1)',
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style>::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: #cbd5e1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.dark ::-webkit-scrollbar-thumb {
|
||||
background-color: #475569;
|
||||
}.neo-border {
|
||||
border: 1px solid black;
|
||||
}
|
||||
.dark .neo-border {
|
||||
border: 1px solid #4a4a4a;
|
||||
}@keyframes float {
|
||||
0% { transform: translateY(0px) rotate(0deg); }
|
||||
50% { transform: translateY(-10px) rotate(2deg); }
|
||||
100% { transform: translateY(0px) rotate(0deg); }
|
||||
}
|
||||
.floating-shape {
|
||||
animation: float 6s ease-in-out infinite;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-background-light dark:bg-background-dark text-text-light dark:text-text-dark font-sans antialiased min-h-screen transition-colors duration-200">
|
||||
<div class="bg-primary w-full py-2 px-4 border-b border-black dark:border-border-dark flex justify-center items-center text-xs font-bold font-display tracking-wide text-black">
|
||||
<span>DISCOVER THE FUTURE OF AI AGENTS </span>
|
||||
<span class="material-icons text-sm ml-2">arrow_forward</span>
|
||||
</div>
|
||||
<header class="w-full border-b border-black dark:border-border-dark bg-background-light dark:bg-background-dark sticky top-0 z-50">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex justify-between items-center h-16">
|
||||
<div class="flex-shrink-0 flex items-center gap-2">
|
||||
<span class="material-icons text-3xl text-black dark:text-primary">smart_toy</span>
|
||||
<span class="font-display font-bold text-xl tracking-tight">Agent Park</span>
|
||||
</div>
|
||||
<nav class="hidden md:flex space-x-8 items-center">
|
||||
<a class="font-display text-sm font-bold hover:text-secondary dark:hover:text-primary transition-colors" href="#">HOME</a>
|
||||
<a class="font-display text-sm font-bold hover:text-secondary dark:hover:text-primary transition-colors" href="#">PROJECTS</a>
|
||||
<a class="font-display text-sm font-bold hover:text-secondary dark:hover:text-primary transition-colors" href="#">BLOG</a>
|
||||
<a class="font-display text-sm font-bold hover:text-secondary dark:hover:text-primary transition-colors" href="#">ABOUT</a>
|
||||
</nav>
|
||||
<div class="hidden md:flex items-center space-x-4">
|
||||
<button class="font-display text-sm font-bold hover:opacity-70">中文 / EN</button>
|
||||
<a class="bg-white dark:bg-surface-dark border border-black dark:border-white px-4 py-2 font-display text-sm font-bold shadow-neobrutalism hover:shadow-neobrutalism-hover hover:translate-x-[2px] hover:translate-y-[2px] transition-all" href="#">
|
||||
SUBMIT PROJECT
|
||||
</a>
|
||||
</div>
|
||||
<div class="md:hidden flex items-center">
|
||||
<button class="text-text-light dark:text-text-dark hover:text-gray-600 focus:outline-none">
|
||||
<span class="material-icons">menu</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<main class="relative overflow-hidden">
|
||||
<div class="absolute top-20 left-10 w-24 h-24 border border-black dark:border-gray-600 rounded-full opacity-20 floating-shape hidden lg:block"></div>
|
||||
<div class="absolute top-40 right-20 w-32 h-20 border border-black dark:border-gray-600 rounded-[2rem] transform -rotate-12 opacity-20 floating-shape hidden lg:block" style="animation-delay: 1s;"></div>
|
||||
<section class="max-w-4xl mx-auto px-4 py-20 text-center relative z-10">
|
||||
<h1 class="font-display text-5xl md:text-7xl font-bold mb-6 tracking-tight leading-tight">
|
||||
AI PROJECT <br class="hidden md:block"/> NAVIGATOR
|
||||
</h1>
|
||||
<p class="text-lg md:text-xl text-gray-600 dark:text-gray-300 mb-10 max-w-2xl mx-auto font-sans">
|
||||
Discover and explore high-quality AI projects from across the web. Curated for developers and enthusiasts.
|
||||
</p>
|
||||
<div class="max-w-2xl mx-auto relative group">
|
||||
<div class="absolute -inset-1 bg-black dark:bg-primary rounded-lg blur opacity-25 group-hover:opacity-50 transition duration-200"></div>
|
||||
<div class="relative flex items-center">
|
||||
<div class="absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none">
|
||||
<span class="material-icons text-gray-400">search</span>
|
||||
</div>
|
||||
<input class="block w-full pl-12 pr-4 py-4 bg-surface-light dark:bg-surface-dark border-2 border-black dark:border-gray-600 text-text-light dark:text-text-dark placeholder-gray-500 focus:ring-0 focus:border-black dark:focus:border-primary font-display shadow-neobrutalism transition-all" placeholder="Search AI projects..." type="text"/>
|
||||
<button class="absolute inset-y-2 right-2 px-4 bg-primary text-black font-bold font-display text-sm border border-black hover:bg-yellow-400 transition-colors">
|
||||
SEARCH
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 mb-16">
|
||||
<h2 class="font-display text-xl font-bold mb-6 border-b-2 border-black dark:border-gray-700 pb-2 inline-block">BROWSE BY TAGS</h2>
|
||||
<div class="flex flex-wrap gap-3">
|
||||
<a class="px-4 py-2 bg-white dark:bg-surface-dark border border-black dark:border-gray-500 font-display text-sm font-bold hover:bg-primary hover:text-black transition-colors shadow-neobrutalism-sm" href="#">
|
||||
Coding Assistant <span class="ml-1 opacity-60 text-xs">2</span>
|
||||
</a>
|
||||
<a class="px-4 py-2 bg-white dark:bg-surface-dark border border-black dark:border-gray-500 font-display text-sm font-bold hover:bg-primary hover:text-black transition-colors shadow-neobrutalism-sm" href="#">
|
||||
Chat AI <span class="ml-1 opacity-60 text-xs">2</span>
|
||||
</a>
|
||||
<a class="px-4 py-2 bg-white dark:bg-surface-dark border border-black dark:border-gray-500 font-display text-sm font-bold hover:bg-primary hover:text-black transition-colors shadow-neobrutalism-sm" href="#">
|
||||
Data Analysis <span class="ml-1 opacity-60 text-xs">4</span>
|
||||
</a>
|
||||
<a class="px-4 py-2 bg-white dark:bg-surface-dark border border-black dark:border-gray-500 font-display text-sm font-bold hover:bg-primary hover:text-black transition-colors shadow-neobrutalism-sm" href="#">
|
||||
Image Gen <span class="ml-1 opacity-60 text-xs">2</span>
|
||||
</a>
|
||||
<a class="px-4 py-2 bg-white dark:bg-surface-dark border border-black dark:border-gray-500 font-display text-sm font-bold hover:bg-primary hover:text-black transition-colors shadow-neobrutalism-sm" href="#">
|
||||
Automation <span class="ml-1 opacity-60 text-xs">1</span>
|
||||
</a>
|
||||
<a class="px-4 py-2 bg-white dark:bg-surface-dark border border-black dark:border-gray-500 font-display text-sm font-bold hover:bg-primary hover:text-black transition-colors shadow-neobrutalism-sm" href="#">
|
||||
LLMs <span class="ml-1 opacity-60 text-xs">8</span>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
<section class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-24">
|
||||
<div class="flex items-end justify-between mb-8">
|
||||
<h2 class="font-display text-3xl font-bold">FEATURED PROJECTS</h2>
|
||||
<a class="hidden md:flex items-center font-display text-sm font-bold hover:underline" href="#">
|
||||
VIEW ALL <span class="material-icons text-sm ml-1">arrow_forward</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
<article class="bg-white dark:bg-surface-dark border-2 border-black dark:border-gray-600 p-6 shadow-neobrutalism hover:shadow-neobrutalism-hover hover:-translate-y-1 transition-all duration-200 flex flex-col h-full">
|
||||
<div class="flex justify-between items-start mb-4">
|
||||
<h3 class="font-display text-2xl font-bold">n8n</h3>
|
||||
<span class="material-icons text-gray-400">auto_awesome</span>
|
||||
</div>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 flex-grow font-sans leading-relaxed">
|
||||
Open-source workflow automation tool. Connect various services and APIs through a visual interface to build complex automations without code.
|
||||
</p>
|
||||
<div class="mt-auto">
|
||||
<div class="flex flex-wrap gap-2 mb-4">
|
||||
<span class="bg-gray-100 dark:bg-gray-700 px-2 py-1 text-xs font-mono border border-black dark:border-gray-500">Automation</span>
|
||||
<span class="bg-gray-100 dark:bg-gray-700 px-2 py-1 text-xs font-mono border border-black dark:border-gray-500">Workflow</span>
|
||||
</div>
|
||||
<a class="inline-flex items-center font-display font-bold text-sm hover:text-secondary dark:hover:text-primary group" href="#">
|
||||
VIEW DETAILS
|
||||
<span class="material-icons text-sm ml-1 transform group-hover:translate-x-1 transition-transform">arrow_forward</span>
|
||||
</a>
|
||||
</div>
|
||||
</article>
|
||||
<article class="bg-white dark:bg-surface-dark border-2 border-black dark:border-gray-600 p-6 shadow-neobrutalism hover:shadow-neobrutalism-hover hover:-translate-y-1 transition-all duration-200 flex flex-col h-full">
|
||||
<div class="flex justify-between items-start mb-4">
|
||||
<h3 class="font-display text-2xl font-bold">Stable Diffusion</h3>
|
||||
<span class="material-icons text-gray-400">image</span>
|
||||
</div>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 flex-grow font-sans leading-relaxed">
|
||||
Open-source image generation model. Supports local deployment and custom training, enabling powerful creative workflows.
|
||||
</p>
|
||||
<div class="mt-auto">
|
||||
<div class="flex flex-wrap gap-2 mb-4">
|
||||
<span class="bg-gray-100 dark:bg-gray-700 px-2 py-1 text-xs font-mono border border-black dark:border-gray-500">Image Gen</span>
|
||||
<span class="bg-gray-100 dark:bg-gray-700 px-2 py-1 text-xs font-mono border border-black dark:border-gray-500">Open Source</span>
|
||||
</div>
|
||||
<a class="inline-flex items-center font-display font-bold text-sm hover:text-secondary dark:hover:text-primary group" href="#">
|
||||
VIEW DETAILS
|
||||
<span class="material-icons text-sm ml-1 transform group-hover:translate-x-1 transition-transform">arrow_forward</span>
|
||||
</a>
|
||||
</div>
|
||||
</article>
|
||||
<article class="bg-white dark:bg-surface-dark border-2 border-black dark:border-gray-600 p-6 shadow-neobrutalism hover:shadow-neobrutalism-hover hover:-translate-y-1 transition-all duration-200 flex flex-col h-full">
|
||||
<div class="flex justify-between items-start mb-4">
|
||||
<h3 class="font-display text-2xl font-bold">Midjourney</h3>
|
||||
<span class="material-icons text-gray-400">palette</span>
|
||||
</div>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 flex-grow font-sans leading-relaxed">
|
||||
Powerful AI image generation tool. Create exquisite images through text descriptions with industry-leading artistic quality.
|
||||
</p>
|
||||
<div class="mt-auto">
|
||||
<div class="flex flex-wrap gap-2 mb-4">
|
||||
<span class="bg-gray-100 dark:bg-gray-700 px-2 py-1 text-xs font-mono border border-black dark:border-gray-500">Image Gen</span>
|
||||
<span class="bg-gray-100 dark:bg-gray-700 px-2 py-1 text-xs font-mono border border-black dark:border-gray-500">Art</span>
|
||||
</div>
|
||||
<a class="inline-flex items-center font-display font-bold text-sm hover:text-secondary dark:hover:text-primary group" href="#">
|
||||
VIEW DETAILS
|
||||
<span class="material-icons text-sm ml-1 transform group-hover:translate-x-1 transition-transform">arrow_forward</span>
|
||||
</a>
|
||||
</div>
|
||||
</article>
|
||||
<article class="bg-white dark:bg-surface-dark border-2 border-black dark:border-gray-600 p-6 shadow-neobrutalism hover:shadow-neobrutalism-hover hover:-translate-y-1 transition-all duration-200 flex flex-col h-full">
|
||||
<div class="flex justify-between items-start mb-4">
|
||||
<h3 class="font-display text-2xl font-bold">ChatGPT</h3>
|
||||
<span class="material-icons text-gray-400">chat</span>
|
||||
</div>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 flex-grow font-sans leading-relaxed">
|
||||
Large language model developed by OpenAI. Supports conversation, writing, coding, and a wide variety of tasks.
|
||||
</p>
|
||||
<div class="mt-auto">
|
||||
<div class="flex flex-wrap gap-2 mb-4">
|
||||
<span class="bg-gray-100 dark:bg-gray-700 px-2 py-1 text-xs font-mono border border-black dark:border-gray-500">Chat AI</span>
|
||||
<span class="bg-gray-100 dark:bg-gray-700 px-2 py-1 text-xs font-mono border border-black dark:border-gray-500">Coding Assistant</span>
|
||||
</div>
|
||||
<a class="inline-flex items-center font-display font-bold text-sm hover:text-secondary dark:hover:text-primary group" href="#">
|
||||
VIEW DETAILS
|
||||
<span class="material-icons text-sm ml-1 transform group-hover:translate-x-1 transition-transform">arrow_forward</span>
|
||||
</a>
|
||||
</div>
|
||||
</article>
|
||||
<article class="bg-white dark:bg-surface-dark border-2 border-black dark:border-gray-600 p-6 shadow-neobrutalism hover:shadow-neobrutalism-hover hover:-translate-y-1 transition-all duration-200 flex flex-col h-full">
|
||||
<div class="flex justify-between items-start mb-4">
|
||||
<h3 class="font-display text-2xl font-bold">Claude</h3>
|
||||
<span class="material-icons text-gray-400">psychology</span>
|
||||
</div>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6 flex-grow font-sans leading-relaxed">
|
||||
AI assistant developed by Anthropic. Excels at analysis, writing, and coding tasks with a focus on safety and reliability.
|
||||
</p>
|
||||
<div class="mt-auto">
|
||||
<div class="flex flex-wrap gap-2 mb-4">
|
||||
<span class="bg-gray-100 dark:bg-gray-700 px-2 py-1 text-xs font-mono border border-black dark:border-gray-500">Chat AI</span>
|
||||
<span class="bg-gray-100 dark:bg-gray-700 px-2 py-1 text-xs font-mono border border-black dark:border-gray-500">Analysis</span>
|
||||
</div>
|
||||
<a class="inline-flex items-center font-display font-bold text-sm hover:text-secondary dark:hover:text-primary group" href="#">
|
||||
VIEW DETAILS
|
||||
<span class="material-icons text-sm ml-1 transform group-hover:translate-x-1 transition-transform">arrow_forward</span>
|
||||
</a>
|
||||
</div>
|
||||
</article>
|
||||
<article class="bg-primary border-2 border-black dark:border-gray-600 p-6 shadow-neobrutalism hover:shadow-neobrutalism-hover hover:-translate-y-1 transition-all duration-200 flex flex-col h-full justify-center items-center text-center">
|
||||
<div class="bg-white p-4 rounded-full border border-black mb-4">
|
||||
<span class="material-icons text-3xl text-black">add</span>
|
||||
</div>
|
||||
<h3 class="font-display text-2xl font-bold text-black mb-2">Submit Your Project</h3>
|
||||
<p class="text-black mb-6 font-sans text-sm px-4">
|
||||
Have an AI tool worth sharing? Add it to Agent Park.
|
||||
</p>
|
||||
<a class="bg-black text-white px-6 py-2 font-display text-sm font-bold border border-black hover:bg-white hover:text-black transition-colors" href="#">
|
||||
SUBMIT NOW
|
||||
</a>
|
||||
</article>
|
||||
</div>
|
||||
<div class="mt-8 text-center md:hidden">
|
||||
<a class="inline-flex items-center font-display text-sm font-bold border-b-2 border-black dark:border-white pb-1" href="#">
|
||||
VIEW ALL PROJECTS <span class="material-icons text-sm ml-1">arrow_forward</span>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
<section class="border-t-2 border-black dark:border-gray-600">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2">
|
||||
<div class="bg-primary p-12 md:p-20 border-b md:border-b-0 md:border-r-2 border-black dark:border-gray-600 flex flex-col justify-center">
|
||||
<h2 class="font-display text-4xl font-bold text-black mb-4">STAY UPDATED</h2>
|
||||
<p class="font-sans text-black mb-8 max-w-md">
|
||||
Get the latest AI tools and trends delivered straight to your inbox. No spam, just intelligence.
|
||||
</p>
|
||||
<form class="space-y-4 max-w-md">
|
||||
<input class="w-full bg-background-light border border-black p-3 font-display text-sm placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-black" placeholder="E-mail" type="email"/>
|
||||
<div class="flex items-center gap-2">
|
||||
<input class="border-black text-black focus:ring-0" id="consent" type="checkbox"/>
|
||||
<label class="text-xs font-bold font-display text-black" for="consent">Subscribe to Agent Park updates</label>
|
||||
</div>
|
||||
<button class="bg-white text-black font-display font-bold py-3 px-8 border border-black shadow-neobrutalism hover:translate-x-[2px] hover:translate-y-[2px] hover:shadow-none transition-all">
|
||||
SUBSCRIBE
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="bg-background-light dark:bg-background-dark p-12 md:p-20 relative overflow-hidden flex items-center justify-center">
|
||||
<div class="relative w-64 h-64">
|
||||
<div class="absolute inset-0 border-2 border-black dark:border-gray-500 bg-white dark:bg-surface-dark transform rotate-3"></div>
|
||||
<div class="absolute inset-0 border-2 border-black dark:border-gray-500 bg-primary transform -rotate-3 translate-x-4 translate-y-4 opacity-80 mix-blend-multiply dark:mix-blend-normal dark:opacity-50"></div>
|
||||
<div class="absolute inset-0 flex items-center justify-center z-10">
|
||||
<span class="material-icons text-8xl text-black dark:text-white">rocket_launch</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<footer class="bg-background-light dark:bg-background-dark border-t border-black dark:border-gray-700 py-12">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="grid grid-cols-2 md:grid-cols-4 gap-8 mb-12">
|
||||
<div>
|
||||
<h4 class="font-display font-bold text-lg mb-4">Agent Park</h4>
|
||||
<ul class="space-y-2 text-sm font-sans text-gray-600 dark:text-gray-400">
|
||||
<li><a class="hover:text-black dark:hover:text-white" href="#">About Us</a></li>
|
||||
<li><a class="hover:text-black dark:hover:text-white" href="#">Contact</a></li>
|
||||
<li><a class="hover:text-black dark:hover:text-white" href="#">Careers</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="font-display font-bold text-lg mb-4">Resources</h4>
|
||||
<ul class="space-y-2 text-sm font-sans text-gray-600 dark:text-gray-400">
|
||||
<li><a class="hover:text-black dark:hover:text-white" href="#">Blog</a></li>
|
||||
<li><a class="hover:text-black dark:hover:text-white" href="#">Newsletter</a></li>
|
||||
<li><a class="hover:text-black dark:hover:text-white" href="#">Documentation</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="font-display font-bold text-lg mb-4">Legal</h4>
|
||||
<ul class="space-y-2 text-sm font-sans text-gray-600 dark:text-gray-400">
|
||||
<li><a class="hover:text-black dark:hover:text-white" href="#">Privacy Policy</a></li>
|
||||
<li><a class="hover:text-black dark:hover:text-white" href="#">Terms of Service</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="font-display font-bold text-lg mb-4">Follow Us</h4>
|
||||
<div class="flex space-x-4">
|
||||
<a class="w-10 h-10 border border-black dark:border-gray-500 flex items-center justify-center hover:bg-primary hover:text-black transition-colors" href="#">
|
||||
<span class="font-display font-bold">X</span>
|
||||
</a>
|
||||
<a class="w-10 h-10 border border-black dark:border-gray-500 flex items-center justify-center hover:bg-primary hover:text-black transition-colors" href="#">
|
||||
<span class="font-display font-bold">Li</span>
|
||||
</a>
|
||||
<a class="w-10 h-10 border border-black dark:border-gray-500 flex items-center justify-center hover:bg-primary hover:text-black transition-colors" href="#">
|
||||
<span class="font-display font-bold">Gh</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-t border-black dark:border-gray-700 pt-8 flex flex-col md:flex-row justify-between items-center">
|
||||
<p class="text-sm text-gray-500 font-display">© 2025 Agent Park. All rights reserved.</p>
|
||||
<div class="mt-4 md:mt-0 font-display text-sm font-bold">
|
||||
DESIGNED FOR AI BUILDERS
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</body></html>
|
||||
@@ -1,344 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"><head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||
<title>Agent Park - AI Project Navigator</title>
|
||||
<script src="https://cdn.tailwindcss.com?plugins=forms,typography"></script>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Space+Mono:ital,wght@0,400;0,700;1,400&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet"/>
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Outlined" rel="stylesheet"/>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
darkMode: "class",
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: "#FFD700", // Gold/Yellow from the screenshots
|
||||
"background-light": "#F5F2EB", // Warm off-white/beige from screenshots
|
||||
"background-dark": "#121212", // Dark mode background
|
||||
"surface-light": "#FFFFFF",
|
||||
"surface-dark": "#1E1E1E",
|
||||
"border-light": "#000000",
|
||||
"border-dark": "#333333",
|
||||
"text-light": "#000000",
|
||||
"text-dark": "#E0E0E0",
|
||||
},
|
||||
fontFamily: {
|
||||
display: ["'Space Mono'", "monospace"], // Monospace for headings/brand
|
||||
sans: ["'Inter'", "sans-serif"], // Clean sans for body
|
||||
},
|
||||
boxShadow: {
|
||||
'neo': '4px 4px 0px 0px rgba(0,0,0,1)', // Brutalist shadow
|
||||
'neo-sm': '2px 2px 0px 0px rgba(0,0,0,1)',
|
||||
'neo-hover': '6px 6px 0px 0px rgba(0,0,0,1)',
|
||||
'neo-dark': '4px 4px 0px 0px rgba(255,215,0,0.5)',
|
||||
},
|
||||
borderRadius: {
|
||||
DEFAULT: "0px", // Sharp corners based on the design
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style>.border-thick {
|
||||
border-width: 2px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-background-light dark:bg-background-dark text-text-light dark:text-text-dark font-sans transition-colors duration-300">
|
||||
<div class="bg-primary text-black text-xs font-display font-bold py-2 text-center border-b-2 border-black">
|
||||
DISCOVER THE FUTURE OF AI AGENTS <span class="material-icons-outlined text-xs align-middle ml-1">arrow_forward</span>
|
||||
</div>
|
||||
<nav class="border-b-2 border-black dark:border-white/20 px-6 py-4 flex justify-between items-center bg-background-light dark:bg-background-dark sticky top-0 z-50">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="material-icons-outlined text-3xl dark:text-primary">smart_toy</span>
|
||||
<span class="font-display font-bold text-xl tracking-tight">Agent Park</span>
|
||||
</div>
|
||||
<div class="hidden md:flex gap-8 font-display text-sm font-bold uppercase tracking-wide">
|
||||
<a class="hover:underline decoration-2 underline-offset-4" href="#">Home</a>
|
||||
<a class="underline decoration-2 underline-offset-4" href="#">Projects</a>
|
||||
<a class="hover:underline decoration-2 underline-offset-4" href="#">Blog</a>
|
||||
<a class="hover:underline decoration-2 underline-offset-4" href="#">About</a>
|
||||
</div>
|
||||
<div class="flex items-center gap-4">
|
||||
<button class="p-2 hover:bg-black/5 dark:hover:bg-white/10 rounded-full transition-colors" onclick="document.documentElement.classList.toggle('dark')">
|
||||
<span class="material-icons-outlined block dark:hidden">dark_mode</span>
|
||||
<span class="material-icons-outlined hidden dark:block text-primary">light_mode</span>
|
||||
</button>
|
||||
<span class="font-display text-xs font-bold hidden sm:inline">中文 / EN</span>
|
||||
<a class="font-display text-xs font-bold border-2 border-black dark:border-white px-4 py-2 hover:bg-black hover:text-white dark:hover:bg-white dark:hover:text-black transition-all shadow-neo-sm hover:shadow-none hover:translate-x-[2px] hover:translate-y-[2px]" href="#">
|
||||
SUBMIT PROJECT
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
<main class="container mx-auto px-4 py-12 md:py-16 max-w-7xl relative">
|
||||
<div class="absolute top-10 left-0 w-24 h-24 border-2 border-black dark:border-white/20 rounded-full opacity-20 pointer-events-none hidden lg:block"></div>
|
||||
<div class="absolute top-20 right-10 w-32 h-20 border-2 border-black dark:border-white/20 rounded-[2rem] opacity-20 pointer-events-none transform rotate-12 hidden lg:block"></div>
|
||||
<div class="text-center mb-16 relative z-10">
|
||||
<h1 class="font-display text-5xl md:text-7xl font-bold mb-6 leading-tight tracking-tighter">
|
||||
PROJECT <br class="md:hidden"/>NAVIGATOR
|
||||
</h1>
|
||||
<p class="text-lg md:text-xl text-gray-600 dark:text-gray-300 max-w-2xl mx-auto font-light leading-relaxed">
|
||||
Discover and explore high-quality AI projects from across the web. <br class="hidden md:inline"/>Curated for developers and enthusiasts.
|
||||
</p>
|
||||
</div>
|
||||
<div class="bg-surface-light dark:bg-surface-dark border-2 border-black dark:border-white/20 p-6 md:p-8 mb-12 shadow-neo dark:shadow-none">
|
||||
<div class="flex flex-col md:flex-row gap-4 mb-8">
|
||||
<div class="relative flex-grow">
|
||||
<span class="material-icons-outlined absolute left-4 top-1/2 transform -translate-y-1/2 text-gray-400">search</span>
|
||||
<input class="w-full pl-12 pr-4 py-3 bg-white dark:bg-black border-2 border-black dark:border-white/30 focus:border-primary focus:ring-0 font-display text-sm placeholder-gray-500" placeholder="Search AI projects..." type="text"/>
|
||||
</div>
|
||||
<div class="relative md:w-1/4">
|
||||
<select class="w-full pl-4 pr-10 py-3 bg-white dark:bg-black border-2 border-black dark:border-white/30 focus:border-primary focus:ring-0 font-display text-sm appearance-none cursor-pointer">
|
||||
<option>All Categories</option>
|
||||
<option>Coding Assistant</option>
|
||||
<option>Image Generation</option>
|
||||
<option>Automation</option>
|
||||
<option>LLMs</option>
|
||||
</select>
|
||||
<span class="material-icons-outlined absolute right-3 top-1/2 transform -translate-y-1/2 pointer-events-none text-gray-500">expand_more</span>
|
||||
</div>
|
||||
<button class="bg-primary border-2 border-black px-8 py-3 font-display font-bold text-sm uppercase hover:bg-yellow-400 transition-colors shadow-neo-sm active:shadow-none active:translate-x-[2px] active:translate-y-[2px] text-black">
|
||||
Search
|
||||
</button>
|
||||
</div>
|
||||
<div class="border-t-2 border-gray-100 dark:border-gray-800 pt-6">
|
||||
<h3 class="font-display font-bold uppercase text-sm mb-4 border-b-2 border-black inline-block dark:border-primary pb-1">Browse by Tags</h3>
|
||||
<div class="flex flex-wrap gap-3">
|
||||
<button class="px-3 py-1 border border-black dark:border-white/40 bg-white dark:bg-transparent font-display text-xs hover:bg-black hover:text-white dark:hover:bg-primary dark:hover:text-black transition-colors flex items-center gap-2 group">
|
||||
Coding Assistant <span class="bg-gray-200 dark:bg-gray-800 dark:group-hover:bg-black/20 px-1.5 py-0.5 text-[10px] rounded-sm group-hover:bg-white group-hover:text-black">12</span>
|
||||
</button>
|
||||
<button class="px-3 py-1 border border-black dark:border-white/40 bg-white dark:bg-transparent font-display text-xs hover:bg-black hover:text-white dark:hover:bg-primary dark:hover:text-black transition-colors flex items-center gap-2 group">
|
||||
Chat AI <span class="bg-gray-200 dark:bg-gray-800 dark:group-hover:bg-black/20 px-1.5 py-0.5 text-[10px] rounded-sm group-hover:bg-white group-hover:text-black">8</span>
|
||||
</button>
|
||||
<button class="px-3 py-1 border border-black dark:border-white/40 bg-black text-white dark:bg-primary dark:text-black font-display text-xs transition-colors flex items-center gap-2">
|
||||
Data Analysis <span class="bg-gray-700 text-white dark:bg-black/20 dark:text-black px-1.5 py-0.5 text-[10px] rounded-sm">4</span>
|
||||
</button>
|
||||
<button class="px-3 py-1 border border-black dark:border-white/40 bg-white dark:bg-transparent font-display text-xs hover:bg-black hover:text-white dark:hover:bg-primary dark:hover:text-black transition-colors flex items-center gap-2 group">
|
||||
Image Gen <span class="bg-gray-200 dark:bg-gray-800 dark:group-hover:bg-black/20 px-1.5 py-0.5 text-[10px] rounded-sm group-hover:bg-white group-hover:text-black">21</span>
|
||||
</button>
|
||||
<button class="px-3 py-1 border border-black dark:border-white/40 bg-white dark:bg-transparent font-display text-xs hover:bg-black hover:text-white dark:hover:bg-primary dark:hover:text-black transition-colors flex items-center gap-2 group">
|
||||
Automation <span class="bg-gray-200 dark:bg-gray-800 dark:group-hover:bg-black/20 px-1.5 py-0.5 text-[10px] rounded-sm group-hover:bg-white group-hover:text-black">15</span>
|
||||
</button>
|
||||
<button class="px-3 py-1 border border-black dark:border-white/40 bg-white dark:bg-transparent font-display text-xs hover:bg-black hover:text-white dark:hover:bg-primary dark:hover:text-black transition-colors flex items-center gap-2 group">
|
||||
LLMs <span class="bg-gray-200 dark:bg-gray-800 dark:group-hover:bg-black/20 px-1.5 py-0.5 text-[10px] rounded-sm group-hover:bg-white group-hover:text-black">34</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-between items-end mb-8 border-b border-black dark:border-white/20 pb-4">
|
||||
<h2 class="font-display font-bold text-3xl uppercase tracking-tight">Featured Projects</h2>
|
||||
<a class="font-display text-xs font-bold uppercase flex items-center gap-1 hover:text-gray-600 dark:hover:text-primary transition-colors" href="#">
|
||||
View All <span class="material-icons-outlined text-sm">arrow_forward</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
<div class="col-span-1 md:col-span-2 bg-purple-200 dark:bg-purple-900/30 border-2 border-black dark:border-white/20 p-0 flex flex-col md:flex-row shadow-neo hover:shadow-neo-hover hover:-translate-y-1 transition-all duration-300 group overflow-hidden">
|
||||
<div class="p-8 flex-1 flex flex-col justify-between relative z-10">
|
||||
<div>
|
||||
<div class="flex justify-between items-start mb-4">
|
||||
<span class="bg-black text-white dark:bg-white dark:text-black font-display text-xs px-2 py-1 font-bold">TOP PICK</span>
|
||||
<span class="material-icons-outlined text-2xl group-hover:rotate-12 transition-transform">auto_awesome</span>
|
||||
</div>
|
||||
<h3 class="font-display font-bold text-3xl mb-3">AutoGPT X</h3>
|
||||
<p class="text-sm md:text-base mb-6 leading-relaxed opacity-90">
|
||||
An experimental open-source application showcasing the capabilities of the GPT-4 language model. This program, driven by GPT-4, chains together LLM "thoughts", to autonomously achieve whatever goal you set.
|
||||
</p>
|
||||
<div class="flex gap-2 flex-wrap mb-6">
|
||||
<span class="border border-black dark:border-white/50 px-2 py-1 text-[10px] uppercase font-display font-bold bg-white/50 dark:bg-black/50">Automation</span>
|
||||
<span class="border border-black dark:border-white/50 px-2 py-1 text-[10px] uppercase font-display font-bold bg-white/50 dark:bg-black/50">Agent</span>
|
||||
</div>
|
||||
</div>
|
||||
<a class="inline-flex items-center font-display font-bold text-sm uppercase group-hover:translate-x-2 transition-transform" href="#">
|
||||
View Details <span class="material-icons-outlined ml-1 text-base">arrow_forward</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="w-full md:w-2/5 bg-purple-300 dark:bg-purple-800/50 border-t-2 md:border-t-0 md:border-l-2 border-black dark:border-white/20 relative overflow-hidden flex items-center justify-center min-h-[200px]">
|
||||
<div class="absolute inset-0 bg-[radial-gradient(circle_at_center,_var(--tw-gradient-stops))] from-white/40 to-transparent"></div>
|
||||
<span class="material-icons-outlined text-9xl opacity-20 rotate-12">psychology</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-white dark:bg-surface-dark border-2 border-black dark:border-white/20 p-6 shadow-neo hover:shadow-neo-hover hover:-translate-y-1 transition-all duration-300 flex flex-col justify-between group">
|
||||
<div>
|
||||
<div class="flex justify-between items-start mb-4 text-gray-400">
|
||||
<span class="material-icons-outlined text-3xl text-black dark:text-white">hub</span>
|
||||
</div>
|
||||
<h3 class="font-display font-bold text-2xl mb-3">n8n</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-6 leading-relaxed">
|
||||
Open-source workflow automation tool. Connect various services and APIs through a visual interface to build complex automations without code.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<div class="flex gap-2 flex-wrap mb-6">
|
||||
<span class="bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 px-2 py-1 text-[10px] uppercase font-display font-bold text-gray-600 dark:text-gray-300">Automation</span>
|
||||
<span class="bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 px-2 py-1 text-[10px] uppercase font-display font-bold text-gray-600 dark:text-gray-300">Workflow</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<a class="inline-flex items-center font-display font-bold text-sm uppercase border-b-2 border-transparent hover:border-primary transition-colors pb-0.5" href="#">
|
||||
View Details <span class="material-icons-outlined ml-1 text-sm">arrow_forward</span>
|
||||
</a>
|
||||
<!-- Neo-brutalism Stars Badge Design -->
|
||||
<div class="inline-flex items-center gap-2 px-3 py-1.5 border-2 border-black dark:border-white/40 bg-white dark:bg-surface-dark shadow-neo-sm hover:shadow-neo transition-all cursor-pointer group/stars" title="42.5k stars on GitHub">
|
||||
<svg class="w-4 h-4 text-primary" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M8 .25a.75.75 0 01.673.418l1.882 3.815 4.21.612a.75.75 0 01.416 1.279l-3.046 2.97.719 4.192a.75.75 0 01-1.088.791L8 12.347l-3.766 1.98a.75.75 0 01-1.088-.79l.72-4.194L.818 6.374a.75.75 0 01.416-1.28l4.21-.611L7.327.668A.75.75 0 018 .25z"/>
|
||||
</svg>
|
||||
<span class="font-display font-bold text-sm text-black dark:text-white">42.5k</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-white dark:bg-surface-dark border-2 border-black dark:border-white/20 p-6 shadow-neo hover:shadow-neo-hover hover:-translate-y-1 transition-all duration-300 flex flex-col justify-between group">
|
||||
<div>
|
||||
<div class="flex justify-between items-start mb-4 text-gray-400">
|
||||
<span class="material-icons-outlined text-3xl text-black dark:text-white">image</span>
|
||||
</div>
|
||||
<h3 class="font-display font-bold text-2xl mb-3">Stable Diffusion</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-6 leading-relaxed">
|
||||
Open-source image generation model. Supports local deployment and custom training, enabling powerful creative workflows.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<div class="flex gap-2 flex-wrap mb-6">
|
||||
<span class="bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 px-2 py-1 text-[10px] uppercase font-display font-bold text-gray-600 dark:text-gray-300">Image Gen</span>
|
||||
<span class="bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 px-2 py-1 text-[10px] uppercase font-display font-bold text-gray-600 dark:text-gray-300">Open Source</span>
|
||||
</div>
|
||||
<a class="inline-flex items-center font-display font-bold text-sm uppercase border-b-2 border-transparent hover:border-primary transition-colors pb-0.5" href="#">
|
||||
View Details <span class="material-icons-outlined ml-1 text-sm">arrow_forward</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-white dark:bg-surface-dark border-2 border-black dark:border-white/20 p-6 shadow-neo hover:shadow-neo-hover hover:-translate-y-1 transition-all duration-300 flex flex-col justify-between group">
|
||||
<div>
|
||||
<div class="flex justify-between items-start mb-4 text-gray-400">
|
||||
<span class="material-icons-outlined text-3xl text-black dark:text-white">palette</span>
|
||||
</div>
|
||||
<h3 class="font-display font-bold text-2xl mb-3">Midjourney</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-6 leading-relaxed">
|
||||
Powerful AI image generation tool. Create exquisite images through text descriptions with industry-leading artistic quality.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<div class="flex gap-2 flex-wrap mb-6">
|
||||
<span class="bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 px-2 py-1 text-[10px] uppercase font-display font-bold text-gray-600 dark:text-gray-300">Image Gen</span>
|
||||
<span class="bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 px-2 py-1 text-[10px] uppercase font-display font-bold text-gray-600 dark:text-gray-300">Art</span>
|
||||
</div>
|
||||
<a class="inline-flex items-center font-display font-bold text-sm uppercase border-b-2 border-transparent hover:border-primary transition-colors pb-0.5" href="#">
|
||||
View Details <span class="material-icons-outlined ml-1 text-sm">arrow_forward</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-white dark:bg-surface-dark border-2 border-black dark:border-white/20 p-6 shadow-neo hover:shadow-neo-hover hover:-translate-y-1 transition-all duration-300 flex flex-col justify-between group">
|
||||
<div>
|
||||
<div class="flex justify-between items-start mb-4 text-gray-400">
|
||||
<span class="material-icons-outlined text-3xl text-black dark:text-white">chat</span>
|
||||
</div>
|
||||
<h3 class="font-display font-bold text-2xl mb-3">ChatGPT</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-6 leading-relaxed">
|
||||
Large language model developed by OpenAI. Supports conversation, writing, coding, and a wide variety of tasks.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<div class="flex gap-2 flex-wrap mb-6">
|
||||
<span class="bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 px-2 py-1 text-[10px] uppercase font-display font-bold text-gray-600 dark:text-gray-300">Chat AI</span>
|
||||
<span class="bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 px-2 py-1 text-[10px] uppercase font-display font-bold text-gray-600 dark:text-gray-300">Assistant</span>
|
||||
</div>
|
||||
<a class="inline-flex items-center font-display font-bold text-sm uppercase border-b-2 border-transparent hover:border-primary transition-colors pb-0.5" href="#">
|
||||
View Details <span class="material-icons-outlined ml-1 text-sm">arrow_forward</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-primary dark:bg-primary border-2 border-black dark:border-black p-6 shadow-neo hover:shadow-neo-hover hover:-translate-y-1 transition-all duration-300 flex flex-col justify-center items-center text-center group">
|
||||
<div class="bg-white dark:bg-black rounded-full w-12 h-12 flex items-center justify-center border-2 border-black mb-4">
|
||||
<span class="material-icons-outlined text-2xl dark:text-primary">add</span>
|
||||
</div>
|
||||
<h3 class="font-display font-bold text-2xl mb-2 text-black">Submit Your Project</h3>
|
||||
<p class="text-sm text-black mb-6 leading-relaxed px-4 font-medium">
|
||||
Have an AI tool worth sharing? Add it to Agent Park.
|
||||
</p>
|
||||
<button class="bg-black text-white dark:bg-black dark:text-primary border-2 border-black dark:border-black px-6 py-2 font-display text-sm font-bold uppercase hover:bg-white hover:text-black dark:hover:bg-white dark:hover:text-black transition-colors">
|
||||
Submit Now
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-16 flex justify-center">
|
||||
<div class="flex border-2 border-black dark:border-white/20 bg-white dark:bg-surface-dark shadow-neo dark:shadow-none">
|
||||
<button class="px-4 py-2 border-r border-black dark:border-white/20 hover:bg-gray-100 dark:hover:bg-white/10 transition-colors disabled:opacity-50">
|
||||
<span class="material-icons-outlined text-sm">arrow_back</span>
|
||||
</button>
|
||||
<button class="px-4 py-2 font-display font-bold text-sm bg-primary border-r border-black dark:border-white/20 text-black">1</button>
|
||||
<button class="px-4 py-2 font-display font-bold text-sm border-r border-black dark:border-white/20 hover:bg-gray-100 dark:hover:bg-white/10 transition-colors">2</button>
|
||||
<button class="px-4 py-2 font-display font-bold text-sm border-r border-black dark:border-white/20 hover:bg-gray-100 dark:hover:bg-white/10 transition-colors">3</button>
|
||||
<button class="px-4 py-2 hover:bg-gray-100 dark:hover:bg-white/10 transition-colors">
|
||||
<span class="material-icons-outlined text-sm">arrow_forward</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<section class="border-t-2 border-black dark:border-white/20 flex flex-col md:flex-row">
|
||||
<div class="w-full md:w-1/2 bg-primary dark:bg-yellow-600 p-12 md:p-20 border-b-2 md:border-b-0 md:border-r-2 border-black dark:border-white/20">
|
||||
<h2 class="font-display font-bold text-4xl mb-4 text-black">STAY UPDATED</h2>
|
||||
<p class="text-black mb-8 font-medium max-w-md">
|
||||
Get the latest AI tools and trends delivered straight to your inbox. No spam, just intelligence.
|
||||
</p>
|
||||
<form class="flex flex-col gap-4 max-w-md">
|
||||
<input class="w-full px-4 py-3 bg-white border-2 border-black font-display text-sm placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-black" placeholder="E-mail" type="email"/>
|
||||
<div class="flex items-center gap-2">
|
||||
<input class="w-4 h-4 border-2 border-black text-black focus:ring-0" id="newsletter-check" type="checkbox"/>
|
||||
<label class="text-xs font-bold font-display uppercase text-black" for="newsletter-check">Subscribe to Agent Park updates</label>
|
||||
</div>
|
||||
<button class="w-32 bg-white text-black border-2 border-black px-6 py-3 font-display font-bold uppercase hover:bg-black hover:text-white transition-colors shadow-[4px_4px_0px_0px_rgba(0,0,0,1)] hover:shadow-none hover:translate-x-[2px] hover:translate-y-[2px]" type="submit">
|
||||
Subscribe
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="w-full md:w-1/2 bg-background-light dark:bg-background-dark p-12 md:p-20 flex items-center justify-center relative overflow-hidden">
|
||||
<div class="relative w-64 h-64">
|
||||
<div class="absolute inset-0 border-2 border-black dark:border-white bg-white dark:bg-surface-dark transform rotate-3 z-10 flex items-center justify-center">
|
||||
<span class="material-icons-outlined text-8xl text-black dark:text-white">rocket_launch</span>
|
||||
</div>
|
||||
<div class="absolute inset-0 border-2 border-black dark:border-white bg-primary dark:bg-primary transform -rotate-3 translate-x-2 translate-y-2 z-0"></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<footer class="bg-background-light dark:bg-background-dark pt-16 pb-8 border-t-2 border-black dark:border-white/20">
|
||||
<div class="container mx-auto px-6 max-w-7xl">
|
||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-12 mb-16">
|
||||
<div>
|
||||
<h3 class="font-display font-bold text-xl mb-6">Agent Park</h3>
|
||||
<ul class="space-y-3 text-sm text-gray-600 dark:text-gray-400">
|
||||
<li><a class="hover:underline" href="#">About Us</a></li>
|
||||
<li><a class="hover:underline" href="#">Contact</a></li>
|
||||
<li><a class="hover:underline" href="#">Careers</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="font-display font-bold text-xl mb-6">Resources</h3>
|
||||
<ul class="space-y-3 text-sm text-gray-600 dark:text-gray-400">
|
||||
<li><a class="hover:underline" href="#">Blog</a></li>
|
||||
<li><a class="hover:underline" href="#">Newsletter</a></li>
|
||||
<li><a class="hover:underline" href="#">Documentation</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="font-display font-bold text-xl mb-6">Legal</h3>
|
||||
<ul class="space-y-3 text-sm text-gray-600 dark:text-gray-400">
|
||||
<li><a class="hover:underline" href="#">Privacy Policy</a></li>
|
||||
<li><a class="hover:underline" href="#">Terms of Service</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="font-display font-bold text-xl mb-6">Follow Us</h3>
|
||||
<div class="flex gap-4">
|
||||
<a class="w-10 h-10 border border-black dark:border-white flex items-center justify-center hover:bg-black hover:text-white dark:hover:bg-white dark:hover:text-black transition-colors font-display font-bold" href="#">X</a>
|
||||
<a class="w-10 h-10 border border-black dark:border-white flex items-center justify-center hover:bg-black hover:text-white dark:hover:bg-white dark:hover:text-black transition-colors font-display font-bold" href="#">Li</a>
|
||||
<a class="w-10 h-10 border border-black dark:border-white flex items-center justify-center hover:bg-black hover:text-white dark:hover:bg-white dark:hover:text-black transition-colors font-display font-bold" href="#">Gh</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-t border-black/20 dark:border-white/20 pt-8 flex flex-col md:flex-row justify-between items-center gap-4">
|
||||
<p class="font-display text-xs text-gray-500">© 2025 Agent Park. All rights reserved.</p>
|
||||
<p class="font-display text-xs font-bold uppercase tracking-wider">Designed for AI Builders</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</body></html>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,161 +0,0 @@
|
||||
# API 测试指南
|
||||
|
||||
## GET /api/events
|
||||
|
||||
获取所有事件:
|
||||
|
||||
```bash
|
||||
curl http://localhost:3000/api/events
|
||||
```
|
||||
|
||||
筛选特定年份:
|
||||
|
||||
```bash
|
||||
curl "http://localhost:3000/api/events?year=2024"
|
||||
```
|
||||
|
||||
限制返回数量:
|
||||
|
||||
```bash
|
||||
curl "http://localhost:3000/api/events?limit=10"
|
||||
```
|
||||
|
||||
分页:
|
||||
|
||||
```bash
|
||||
curl "http://localhost:3000/api/events?offset=10&limit=10"
|
||||
```
|
||||
|
||||
## POST /api/events
|
||||
|
||||
创建单个事件:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/events \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-API-Key: YOUR_API_KEY" \
|
||||
-d '[
|
||||
{
|
||||
"title": "事件标题",
|
||||
"eventDate": "2023-03-14T00:00:00Z",
|
||||
"description": "事件描述(10-500字)",
|
||||
"imageUrl": "https://example.com/image.jpg"
|
||||
}
|
||||
]'
|
||||
```
|
||||
|
||||
批量创建事件:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/events \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-API-Key: YOUR_API_KEY" \
|
||||
-d '[
|
||||
{ "title": "事件1", "eventDate": "2023-01-01T00:00:00Z", "description": "描述1", "imageUrl": "https://example.com/1.jpg" },
|
||||
{ "title": "事件2", "eventDate": "2023-02-01T00:00:00Z", "description": "描述2", "imageUrl": "https://example.com/2.jpg" }
|
||||
]'
|
||||
```
|
||||
|
||||
包含可选字段:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/events \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-API-Key: YOUR_API_KEY" \
|
||||
-d '[
|
||||
{
|
||||
"title": "GPT-4 Release",
|
||||
"titleEn": "GPT-4 发布",
|
||||
"eventDate": "2023-03-14T00:00:00Z",
|
||||
"description": "OpenAI launches multimodal LLM",
|
||||
"descriptionEn": "OpenAI 发布多模态大语言模型",
|
||||
"imageUrl": "https://example.com/gpt4.jpg",
|
||||
"sourceUrl": "https://openai.com/blog/gpt-4"
|
||||
}
|
||||
]'
|
||||
```
|
||||
|
||||
## 验证规则
|
||||
|
||||
### 输入验证 (AIEventInputSchema)
|
||||
|
||||
- `title`: 1-200 字符(必填)
|
||||
- `titleEn`: 最多 200 字符(可选)
|
||||
- `eventDate`: ISO 8601 datetime 格式(必填)
|
||||
- `description`: 10-500 字符(必填)
|
||||
- `descriptionEn`: 最多 500 字符(可选)
|
||||
- `imageUrl`: 有效 URL(必填)
|
||||
- `sourceUrl`: 有效 URL(可选)
|
||||
|
||||
### 查询参数验证 (AIEventQuerySchema)
|
||||
|
||||
- `year`: 4位数字年份(可选)
|
||||
- `limit`: 正整数(可选,默认 100)
|
||||
- `offset`: 非负整数(可选,默认 0)
|
||||
|
||||
## 认证
|
||||
|
||||
所有 POST 请求必须在请求头中包含 API Key:
|
||||
|
||||
```
|
||||
X-API-Key: YOUR_API_KEY
|
||||
```
|
||||
|
||||
## 响应示例
|
||||
|
||||
### 成功响应 (POST)
|
||||
|
||||
```json
|
||||
{
|
||||
"created": 2,
|
||||
"total": 2
|
||||
}
|
||||
```
|
||||
|
||||
### 成功响应 (GET)
|
||||
|
||||
```json
|
||||
{
|
||||
"events": [
|
||||
{
|
||||
"id": "cmkwn6q0300004jjz4lobtkpf",
|
||||
"title": "Transformer论文",
|
||||
"titleEn": null,
|
||||
"eventDate": "2017-06-12T00:00:00.000Z",
|
||||
"description": "Google团队发表Transformer架构",
|
||||
"descriptionEn": null,
|
||||
"imageUrl": "https://images.unsplash.com/photo-1677442136019-21780ecad995?w=800",
|
||||
"sourceUrl": null,
|
||||
"createdAt": "2026-01-27T13:38:39.268Z",
|
||||
"updatedAt": "2026-01-27T13:38:39.268Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 错误响应
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "Validation failed",
|
||||
"details": [
|
||||
{
|
||||
"code": "too_small",
|
||||
"path": ["0", "description"],
|
||||
"message": "String must contain at least 10 character(s)"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 测试记录
|
||||
|
||||
### 2025-01-27 测试结果
|
||||
|
||||
- ✅ GET /api/events - 返回空列表
|
||||
- ✅ POST /api/events - 单个事件创建成功
|
||||
- ✅ GET /api/events - 验证事件已创建(1个事件)
|
||||
- ✅ POST /api/events - 批量创建成功(2个事件)
|
||||
- ✅ GET /api/events?year=2018 - 年份筛选成功(返回2个事件)
|
||||
|
||||
所有基础功能测试通过!
|
||||
@@ -1,548 +0,0 @@
|
||||
# 项目发现工作流 (Project Discovery Workflow)
|
||||
|
||||
本文档详细说明了 AI 项目自动发现和收录的完整工作流程。
|
||||
|
||||
## 📋 工作流概览
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 项目发现完整流程 │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
|
||||
1. n8n 自动化平台
|
||||
│
|
||||
├─ 定期抓取 GitHub/Twitter/HackerNews 等平台
|
||||
├─ 筛选符合条件的项目链接
|
||||
│
|
||||
▼
|
||||
2. 调用去重检查 API (推荐)
|
||||
POST /api/discovery/check-duplicates
|
||||
│
|
||||
├─ 检查 URL 是否已存在任务
|
||||
├─ 检查 URL 对应项目是否已收录
|
||||
├─ 过滤出需要创建的 URL
|
||||
│
|
||||
▼
|
||||
3. 调用创建任务 API
|
||||
POST /api/discovery/tasks
|
||||
│
|
||||
├─ 存入 ProjectDiscoveryTask 表
|
||||
├─ 状态: PENDING
|
||||
│
|
||||
▼
|
||||
4. 手动触发本地命令 (定期执行)
|
||||
/discover-projects
|
||||
│
|
||||
├─ 通过 curl 获取待处理任务
|
||||
├─ 调用 Content Explorer Agent
|
||||
│ ├─ 使用 agent-browser 探索项目
|
||||
│ ├─ 提取项目信息 (README, 代码结构等)
|
||||
│ ├─ 生成结构化 JSON 数据
|
||||
│ └─ 应用内容质量标准
|
||||
│
|
||||
├─ 调用 API Submitter Agent
|
||||
│ ├─ 批量标记任务为 IN_PROGRESS
|
||||
│ ├─ 提交探索数据到完成 API
|
||||
│ └─ 自动重试失败的提交
|
||||
│
|
||||
▼
|
||||
5. 完成任务并入库
|
||||
POST /api/discovery/tasks/{id}/complete
|
||||
│
|
||||
├─ 验证数据格式 (Zod Schema)
|
||||
├─ 多级去重检测 (GitHub/Website URL)
|
||||
├─ 创建或更新 Project
|
||||
├─ 创建 Tag 和关联关系
|
||||
├─ 创建 ExternalLink
|
||||
│
|
||||
├─ 更新任务状态: COMPLETED/FAILED
|
||||
│
|
||||
▼
|
||||
6. 数据已入库,可在前台展示
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 详细步骤说明
|
||||
|
||||
### 步骤 1: n8n 自动收集项目链接
|
||||
|
||||
**平台**: n8n 自动化平台 (独立部署)
|
||||
|
||||
**工作内容**:
|
||||
- 定期抓取 GitHub Trending、Twitter、HackerNews 等平台
|
||||
- 根据关键词筛选 AI 相关项目
|
||||
- 提取项目的基本信息 (名称、链接、简介等)
|
||||
|
||||
**输出数据格式**:
|
||||
```json
|
||||
{
|
||||
"sourceUrl": "https://github.com/langchain-ai/langchain",
|
||||
"sourceType": "github_trending" // 或 "twitter", "hackernews" 等
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 步骤 2: 调用创建任务 API
|
||||
|
||||
**API 端点**: `POST /api/discovery/tasks`
|
||||
|
||||
**调用示例**:
|
||||
```bash
|
||||
curl -X POST https://your-domain.com/api/discovery/tasks \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"apiKey": "YOUR_API_KEY",
|
||||
"tasks": [
|
||||
{
|
||||
"sourceUrl": "https://github.com/langchain-ai/langchain",
|
||||
"sourceType": "github_trending"
|
||||
},
|
||||
{
|
||||
"sourceUrl": "https://github.com/openai/openai-quickstart-python",
|
||||
"sourceType": "github_trending"
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
**数据库变更**:
|
||||
- 在 `ProjectDiscoveryTask` 表中插入新记录
|
||||
- `status` = `PENDING`
|
||||
- `sourceUrl` 和 `sourceType` 来自 n8n
|
||||
- `createdAt` = 当前时间
|
||||
|
||||
---
|
||||
|
||||
### 步骤 2.5: 调用去重检查 API(推荐)
|
||||
|
||||
**API 端点**: `POST /api/discovery/check-duplicates`
|
||||
|
||||
**调用示例**:
|
||||
```bash
|
||||
curl -X POST https://your-domain.com/api/discovery/check-duplicates \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"apiKey": "YOUR_API_KEY",
|
||||
"urls": [
|
||||
"https://github.com/langchain-ai/langchain",
|
||||
"https://github.com/openai/openai-quickstart-python"
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
**返回结果**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"results": [
|
||||
{
|
||||
"url": "https://github.com/langchain-ai/langchain",
|
||||
"shouldCreate": false,
|
||||
"reason": "Task already exists with status PENDING",
|
||||
"existingTask": {
|
||||
"id": "cmxxxxx",
|
||||
"status": "PENDING",
|
||||
"sourceUrl": "https://github.com/langchain-ai/langchain",
|
||||
"createdAt": "2025-01-18T10:00:00Z",
|
||||
"projectId": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/openai/openai-quickstart-python",
|
||||
"shouldCreate": true,
|
||||
"reason": "No existing task or project found"
|
||||
}
|
||||
],
|
||||
"stats": {
|
||||
"total": 2,
|
||||
"shouldCreate": 1,
|
||||
"duplicate": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**去重逻辑**(按优先级):
|
||||
1. **优先级 1**: 检查是否有 PENDING/IN_PROGRESS 的相同 URL 任务
|
||||
- 如果存在 → `shouldCreate: false`
|
||||
- 原因:任务已在处理中,避免重复探索
|
||||
|
||||
2. **优先级 2**: 检查是否有 COMPLETED/FAILED 的相同 URL 任务
|
||||
- 如果存在 → `shouldCreate: false`
|
||||
- 原因:任务已探索过,无需重复
|
||||
|
||||
3. **优先级 3**: 检查 URL 对应的项目是否已存在(通过 ExternalLink)
|
||||
- 如果存在 → `shouldCreate: false`
|
||||
- 原因:项目已通过其他来源收录
|
||||
|
||||
4. **默认**: 允许创建新任务
|
||||
- `shouldCreate: true`
|
||||
|
||||
**n8n 集成建议**:
|
||||
```javascript
|
||||
// n8n Workflow 示例
|
||||
const checkResponse = await fetch('https://your-domain.com/api/discovery/check-duplicates', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
apiKey: 'YOUR_API_KEY',
|
||||
urls: collectedUrls // 从上一步收集的 URL 列表
|
||||
})
|
||||
})
|
||||
|
||||
const { results, stats } = await checkResponse.json()
|
||||
|
||||
// 过滤出应该创建任务的 URL
|
||||
const urlsToCreate = results
|
||||
.filter(r => r.shouldCreate)
|
||||
.map(r => r.url)
|
||||
|
||||
// 只为不重复的 URL 创建任务
|
||||
if (urlsToCreate.length > 0) {
|
||||
await fetch('https://your-domain.com/api/discovery/tasks', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
apiKey: 'YOUR_API_KEY',
|
||||
tasks: urlsToCreate.map(url => ({
|
||||
sourceUrl: url,
|
||||
sourceType: 'github_trending'
|
||||
}))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
console.log(`创建 ${urlsToCreate.length} 个新任务,跳过 ${stats.duplicate} 个重复任务`)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 步骤 3: 手动触发本地命令
|
||||
|
||||
**执行环境**: 本地开发环境 (Local Development)
|
||||
|
||||
**执行命令**:
|
||||
```bash
|
||||
# 处理默认 10 个任务 (每批 3 个)
|
||||
/discover-projects
|
||||
|
||||
# 处理指定数量的任务
|
||||
/discover-projects 20
|
||||
|
||||
# 自定义批次大小
|
||||
/discover-projects 9 --batch=2
|
||||
|
||||
# 处理所有待处理任务
|
||||
/discover-projects all --batch=5
|
||||
```
|
||||
|
||||
**命令执行流程**:
|
||||
1. 通过 curl 调用 `GET /api/discovery/tasks?status=PENDING&limit=N`
|
||||
2. 获取待处理的任务列表
|
||||
3. 分批处理 (默认每批 3 个任务)
|
||||
4. 为每个任务启动 **Content Explorer Agent**
|
||||
|
||||
---
|
||||
|
||||
### 步骤 3.1: Content Explorer Agent (项目探索)
|
||||
|
||||
**Agent 定义**: `.claude/agents/content-explorer-agent.md`
|
||||
|
||||
**核心能力**:
|
||||
- 使用 `agent-browser` 子任务并行探索 GitHub 项目
|
||||
- 访问项目主页、README、代码结构
|
||||
- 提取项目元数据 (名称、描述、标签、链接等)
|
||||
- 生成符合 `ProjectInputSchema` 的 JSON 数据
|
||||
|
||||
**内容质量标准** (参考: `.claude/schemas/project-content-template.md`):
|
||||
- ✅ **描述**: 客观说明功能、突出价值、避免营销术语、10-500字
|
||||
- ✅ **内容**: 从 README 提取并重新组织、符合中文表达习惯
|
||||
- ✅ **链接**: 必须包含 GITHUB 链接、所有链接可访问
|
||||
- ✅ **标签**: 1-10 个标签、按技术/应用/状态分类
|
||||
- ✅ **动态数据**: Star/Fork 等动态数据不写入内容,使用 GitHub Badge
|
||||
|
||||
**输出数据格式**:
|
||||
```json
|
||||
{
|
||||
"name": "LangChain",
|
||||
"nameEn": "LangChain",
|
||||
"description": "开发由 LLM 驱动的应用程序的框架,提供文档加载、文本分割、向量存储等核心组件",
|
||||
"descriptionEn": "Framework for developing applications powered by language models",
|
||||
"content": "## 核心功能\n\n- 文档加载: 支持 PDF、TXT、网页等多种格式\n- 文本分割: 智能分割长文本\n...",
|
||||
"tags": [
|
||||
{ "name": "LLM", "nameEn": "Large Language Model" },
|
||||
{ "name": "框架", "nameEn": "Framework" }
|
||||
],
|
||||
"links": [
|
||||
{ "type": "GITHUB", "url": "https://github.com/langchain-ai/langchain", "title": "GitHub 仓库" },
|
||||
{ "type": "WEBSITE", "url": "https://python.langchain.com", "title": "官方文档" }
|
||||
],
|
||||
"status": "ACTIVE"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 步骤 3.2: API Submitter Agent (数据提交)
|
||||
|
||||
**Agent 定义**: `.claude/agents/api-submitter-agent.md`
|
||||
|
||||
**核心能力**:
|
||||
- 批量标记任务为 `IN_PROGRESS`
|
||||
- 调用 `POST /api/discovery/tasks/{id}/complete` 提交数据
|
||||
- 自动重试失败的提交 (指数退避,最多 3 次)
|
||||
- 处理部分成功/失败情况
|
||||
|
||||
**提交流程**:
|
||||
```
|
||||
1. PATCH /api/discovery/tasks/{id} → status=IN_PROGRESS
|
||||
↓
|
||||
2. POST /api/discovery/tasks/{id}/complete → 提交探索数据
|
||||
↓
|
||||
3. 检查响应
|
||||
├─ 成功 → 标记任务完成
|
||||
├─ 失败 → 重试 (最多 3 次)
|
||||
└─ 最终失败 → 记录错误信息
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 步骤 4: 完成任务并入库
|
||||
|
||||
**API 端点**: `POST /api/discovery/tasks/{id}/complete`
|
||||
|
||||
**处理逻辑** (参考: `src/app/api/discovery/tasks/[id]/complete/route.ts`):
|
||||
|
||||
1. **验证数据格式**: 使用 `ProjectInputSchema` 验证
|
||||
2. **多级去重检测**:
|
||||
- 优先级 1: GitHub URL 精确匹配
|
||||
- 优先级 2: Website URL 精确匹配
|
||||
- 优先级 3: slug 匹配
|
||||
3. **创建或更新项目**:
|
||||
- 如果存在重复项目 → 更新所有字段、标签、链接
|
||||
- 如果不存在 → 创建新项目
|
||||
4. **更新任务状态**:
|
||||
- 成功 → `COMPLETED`
|
||||
- 失败 → `FAILED` (记录错误信息)
|
||||
|
||||
**数据库变更**:
|
||||
- `Project` 表: 创建或更新记录
|
||||
- `Tag` 表: Upsert 标签
|
||||
- `ProjectTag` 表: 创建关联关系
|
||||
- `ExternalLink` 表: 创建或更新链接
|
||||
- `ProjectDiscoveryTask` 表: 更新 `status`、`projectId`、`completedAt`
|
||||
|
||||
---
|
||||
|
||||
## 🗂️ 数据模型关系
|
||||
|
||||
```
|
||||
ProjectDiscoveryTask (任务表)
|
||||
├─ id: String (主键)
|
||||
├─ status: TaskStatus (PENDING/IN_PROGRESS/COMPLETED/FAILED)
|
||||
├─ sourceUrl: String (n8n 提供的原始 URL)
|
||||
├─ sourceType: String (github_trending/twitter/hackernews)
|
||||
├─ explorationData: Json (Agent 探索结果)
|
||||
├─ explorationSummary: String (探索摘要)
|
||||
├─ projectId: String (关联到 Project.id)
|
||||
├─ errorMessage: String (失败原因)
|
||||
└─ createdAt/startedAt/completedAt: DateTime
|
||||
|
||||
Project (项目表) ← 通过 projectId 关联
|
||||
├─ id, name, nameEn, slug
|
||||
├─ description, descriptionEn
|
||||
├─ content, contentEn
|
||||
├─ status (ACTIVE/ARCHIVED)
|
||||
└─ 关联: tags, links, discoveryTasks
|
||||
|
||||
Tag (标签表)
|
||||
└─ 通过 ProjectTag 多对多关联
|
||||
|
||||
ExternalLink (外部链接表)
|
||||
└─ 通过 projectId 一对多关联
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 环境配置
|
||||
|
||||
### 环境变量
|
||||
|
||||
```env
|
||||
# .env.local (本地开发)
|
||||
WEBHOOK_API_KEY=sk_live_your_secure_api_key_min_32_chars # 用于调用完成 API
|
||||
|
||||
# 生产环境 (Vercel Dashboard 配置)
|
||||
DATABASE_URL=postgres://...
|
||||
WEBHOOK_API_KEY=sk_live_your_secure_api_key_min_32_chars
|
||||
```
|
||||
|
||||
### 依赖服务
|
||||
|
||||
1. **n8n 平台**:
|
||||
- 独立部署 (自托管或云服务)
|
||||
- 配置定时工作流 (Workflow)
|
||||
- 存储 `WEBHOOK_API_KEY` 用于 API 调用
|
||||
|
||||
2. **本地开发环境**:
|
||||
- Node.js 18+
|
||||
- pnpm 包管理器
|
||||
- Claude Code CLI (支持斜杠命令)
|
||||
|
||||
3. **生产环境**:
|
||||
- Vercel (Next.js 部署)
|
||||
- Neon PostgreSQL (数据库)
|
||||
|
||||
---
|
||||
|
||||
## 📊 执行监控
|
||||
|
||||
### 查看待处理任务
|
||||
|
||||
```bash
|
||||
# 查询待处理任务数量
|
||||
curl https://your-domain.com/api/discovery/tasks?status=PENDING&limit=100
|
||||
|
||||
# 查询进行中的任务
|
||||
curl https://your-domain.com/api/discovery/tasks?status=IN_PROGRESS
|
||||
|
||||
# 查询失败的任务 (需要重试)
|
||||
curl https://your-domain.com/api/discovery/tasks?status=FAILED
|
||||
```
|
||||
|
||||
### 重试失败任务
|
||||
|
||||
```bash
|
||||
# 手动重试失败的任务
|
||||
/discover-projects 10 --status=FAILED
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 质量保障
|
||||
|
||||
### 内容质量标准 (详细参考: `.claude/schemas/project-content-template.md`)
|
||||
|
||||
1. **描述要求**:
|
||||
- 清晰说明项目的核心功能
|
||||
- 突出项目的独特价值
|
||||
- 避免使用营销术语 ("最好"、"第一"、"革命性" 等)
|
||||
- 字数控制在 10-500 字
|
||||
|
||||
2. **内容要求**:
|
||||
- 从项目 README 提取并重新组织
|
||||
- 避免机械翻译,符合中文表达习惯
|
||||
- 支持 Markdown 格式
|
||||
- 动态数据 (Star/Fork) 不写入内容
|
||||
|
||||
3. **链接要求**:
|
||||
- 必须包含 GITHUB 链接
|
||||
- 所有链接必须可访问
|
||||
- 链接类型必须正确 (WEBSITE/GITHUB/HUGGINGFACE/PAPER)
|
||||
|
||||
4. **标签要求**:
|
||||
- 1-10 个标签
|
||||
- 按技术栈/应用领域/开发状态分类
|
||||
- 中英文对应
|
||||
|
||||
### 数据验证
|
||||
|
||||
所有提交的数据必须通过 `ProjectInputSchema` 验证 (详见 `src/lib/validations.ts`):
|
||||
|
||||
```typescript
|
||||
ProjectInputSchema {
|
||||
name: string (1-200字符, 必填)
|
||||
description: string (10-500字符, 必填)
|
||||
tags: Tag[] (1-10个, 必填)
|
||||
links: ExternalLink[] (1-10个, 必填)
|
||||
nameEn?: string (1-200字符)
|
||||
descriptionEn?: string
|
||||
content?: string (Markdown, 最多10000字符)
|
||||
contentEn?: string
|
||||
status?: "ACTIVE" | "ARCHIVED"
|
||||
source?: string
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 第一次使用
|
||||
|
||||
1. **配置 n8n 工作流**:
|
||||
- 创建新的 n8n Workflow
|
||||
- 配置定时触发器 (如每天凌晨 2 点)
|
||||
- 添加 HTTP Request 节点调用 `POST /api/discovery/tasks`
|
||||
|
||||
2. **本地执行命令**:
|
||||
```bash
|
||||
# 启动开发服务器 (如果未运行)
|
||||
pnpm dev
|
||||
|
||||
# 执行项目发现命令
|
||||
/discover-projects
|
||||
```
|
||||
|
||||
3. **查看结果**:
|
||||
- 访问 https://your-domain.com 查看新收录的项目
|
||||
- 检查数据库确认数据正确性
|
||||
|
||||
### 日常维护
|
||||
|
||||
1. **定期执行命令** (建议每天 1-2 次):
|
||||
```bash
|
||||
/discover-projects 20
|
||||
```
|
||||
|
||||
2. **监控失败任务**:
|
||||
- 检查 `status=FAILED` 的任务
|
||||
- 分析错误原因 (网络问题、数据格式等)
|
||||
- 必要时手动重试
|
||||
|
||||
3. **优化内容质量**:
|
||||
- 随机抽查已收录项目的描述和内容
|
||||
- 调整 Agent 的提示词以提升质量
|
||||
|
||||
---
|
||||
|
||||
## 🔍 故障排查
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **任务长时间处于 IN_PROGRESS 状态**:
|
||||
- 可能原因: Agent 探索超时、网络问题
|
||||
- 解决方案: 手动更新任务状态为 PENDING 后重试
|
||||
|
||||
2. **大量任务失败**:
|
||||
- 检查 `errorMessage` 字段
|
||||
- 常见原因: 数据格式不正确、URL 无法访问、API Key 错误
|
||||
|
||||
3. **重复项目被创建**:
|
||||
- 检查去重逻辑是否正常工作
|
||||
- 确认 `ExternalLink` 表的索引 `idx_link_type_url` 存在
|
||||
|
||||
4. **n8n 无法调用 API**:
|
||||
- 检查 `WEBHOOK_API_KEY` 是否正确配置
|
||||
- 确认 API 端点可访问
|
||||
- 查看 n8n 执行日志
|
||||
|
||||
---
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
- **API 参考**: `docs/api-reference.md`
|
||||
- **数据模型**: `prisma/schema.prisma`
|
||||
- **验证规则**: `src/lib/validations.ts`
|
||||
- **Agent 定义**: `.claude/agents/content-explorer-agent.md`
|
||||
- **Agent 定义**: `.claude/agents/api-submitter-agent.md`
|
||||
- **内容质量标准**: `.claude/schemas/project-content-template.md`
|
||||
- **项目主文档**: `CLAUDE.md`
|
||||
|
||||
---
|
||||
|
||||
## 📝 更新日志
|
||||
|
||||
- **2025-01-18**: 创建文档,记录完整的项目发现工作流
|
||||
@@ -1,106 +0,0 @@
|
||||
# Timeline E2E 测试指南
|
||||
|
||||
## 使用 chrome-devtools-mcp 测试
|
||||
|
||||
### 1. 启动测试环境
|
||||
|
||||
```bash
|
||||
# 确保开发服务器运行
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
### 2. 页面加载测试
|
||||
|
||||
使用 `new_page` 或 `navigate_page`:
|
||||
```
|
||||
URL: http://localhost:3000/timeline
|
||||
预期: 页面成功加载,中文路径重定向到 /zh/timeline
|
||||
```
|
||||
|
||||
使用 `take_snapshot`:
|
||||
- 验证页面结构正确,包含 header 和 timeline sections
|
||||
- 验证导航菜单包含"AI 时间轴"链接
|
||||
|
||||
### 3. 数据验证
|
||||
|
||||
使用 `evaluate_script`:
|
||||
```javascript
|
||||
() => {
|
||||
const yearSections = document.querySelectorAll('section');
|
||||
const eventCards = document.querySelectorAll('.stack-card');
|
||||
|
||||
return {
|
||||
yearCount: yearSections.length,
|
||||
eventCount: eventCards.length,
|
||||
hasHeader: document.querySelector('h1') !== null
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
预期结果:
|
||||
```json
|
||||
{
|
||||
"yearCount": 2,
|
||||
"eventCount": 3,
|
||||
"hasHeader": true
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 无控制台错误
|
||||
|
||||
使用 `list_console_messages` with `types: ["error", "warn"]`:
|
||||
- Expected: 空数组或仅资源预加载警告(可忽略)
|
||||
|
||||
### 5. 响应式测试
|
||||
|
||||
使用 `resize_page`:
|
||||
- 桌面: 1920x1080
|
||||
- 移动: 375x667 (iPhone SE)
|
||||
|
||||
验证: 布局在不同尺寸下正常显示,移动端显示汉堡菜单
|
||||
|
||||
### 6. 截图对比
|
||||
|
||||
使用 `take_screenshot`:
|
||||
- 保存路径: `tests/screenshots/timeline-page.png`
|
||||
- 手动对比与设计原型
|
||||
- 验证视觉风格符合 Neo-brutalism 设计
|
||||
|
||||
## 测试记录
|
||||
|
||||
### 2025-01-27 测试结果
|
||||
|
||||
- ✅ 页面加载成功(自动重定向到 /zh/timeline)
|
||||
- ✅ 数据渲染正确(2年3事件:2018年2个,2017年1个)
|
||||
- ✅ 年份降序排列(2018 → 2017)
|
||||
- ✅ 导航菜单"AI 时间轴"链接正常
|
||||
- ✅ 无控制台错误(仅1个资源预加载警告)
|
||||
- ✅ 移动端响应式布局正常
|
||||
- ✅ 桌面端截图已保存
|
||||
|
||||
### 测试数据
|
||||
|
||||
**2018年事件(2个):**
|
||||
1. BERT发布 - Google发布BERT预训练模型 (2018/10/11)
|
||||
2. GPT-1发布 - OpenAI发布第一代GPT模型 (2018/6/11)
|
||||
|
||||
**2017年事件(1个):**
|
||||
1. Transformer论文 - Google团队发表Transformer架构 (2017/6/12)
|
||||
|
||||
### 测试环境
|
||||
|
||||
- Node.js: v22
|
||||
- Next.js: 15.1.11
|
||||
- 浏览器: Chrome (chrome-devtools-mcp)
|
||||
- 测试时间: 2025-01-27 21:40
|
||||
|
||||
### 已知问题
|
||||
|
||||
无
|
||||
|
||||
### 后续优化
|
||||
|
||||
- 添加更多历史事件数据
|
||||
- 实现搜索和筛选功能
|
||||
- 添加事件详情页面
|
||||
- 优化移动端卡片间距
|
||||
@@ -1,145 +0,0 @@
|
||||
# n8n Tag Janitor Workflow
|
||||
|
||||
## Overview
|
||||
|
||||
Daily automated workflow to clean up duplicate/similar tags using AI semantic analysis.
|
||||
|
||||
## Workflow Structure
|
||||
|
||||
[Cron] → [HTTP GET /api/tags] → [Code: Preprocess] → [AI: Generate Plan] → [Code: Validate JSON] → [HTTP POST /api/tags/maintenance] → [Notification]
|
||||
|
||||
## Node Configuration
|
||||
|
||||
### 1. Schedule Trigger (Cron)
|
||||
|
||||
- Trigger: Daily at 03:00 UTC
|
||||
- Timezone: UTC
|
||||
|
||||
### 2. HTTP Request - Fetch Tags
|
||||
|
||||
- Method: GET
|
||||
- URL: `{{$env.SITE_BASE_URL}}/api/tags`
|
||||
- Response: JSON with `.tags` array
|
||||
|
||||
### 3. Code Node - Preprocess
|
||||
|
||||
Purpose: Format tags for LLM input, handle chunking if >200 tags
|
||||
|
||||
```javascript
|
||||
const tags = $input.first().json.tags;
|
||||
const formatted = tags.map((t) => ({
|
||||
id: t.id,
|
||||
name: t.name,
|
||||
nameEn: t.nameEn || "",
|
||||
projectCount: t._count.projects,
|
||||
}));
|
||||
// Sort by projectCount desc for prioritization
|
||||
formatted.sort((a, b) => b.projectCount - a.projectCount);
|
||||
return [{ json: { tags: formatted, total: formatted.length } }];
|
||||
```
|
||||
|
||||
### 4. AI Node - Generate Merge Plan
|
||||
|
||||
Model: GPT-4o / Claude 3.5 Sonnet
|
||||
Temperature: 0.1 (deterministic)
|
||||
|
||||
Prompt Template:
|
||||
|
||||
```
|
||||
You are a tag management expert. Analyze these tags and identify:
|
||||
1. Semantic duplicates that should be merged (e.g., "机器学习" and "ML" → keep "机器学习" with nameEn "Machine Learning")
|
||||
2. Tags missing English names that need nameEn补全
|
||||
|
||||
Tags (JSON):
|
||||
{{$json.tags}}
|
||||
|
||||
Output STRICT JSON (no markdown, no explanation):
|
||||
{
|
||||
"merges": [
|
||||
{
|
||||
"target": { "name": "保留的标签名", "nameEn": "Canonical English Name" },
|
||||
"sourceTagIds": ["id1", "id2"]
|
||||
}
|
||||
],
|
||||
"updates": [
|
||||
{ "tagId": "id", "nameEn": "English Name" }
|
||||
]
|
||||
}
|
||||
|
||||
Rules:
|
||||
- Keep the tag with higher projectCount as target
|
||||
- For merges, target can be { "id": "existing_id" } if keeping existing tag, or { "name": "...", "nameEn": "..." } to create new
|
||||
- Only include tags that NEED action (empty arrays if nothing to do)
|
||||
- nameEn should be proper English, not pinyin
|
||||
- Common tech terms: 机器学习=Machine Learning, 深度学习=Deep Learning, 自然语言处理=NLP
|
||||
```
|
||||
|
||||
### 5. Code Node - Validate & Parse
|
||||
|
||||
```javascript
|
||||
const response = $input.first().json;
|
||||
let plan;
|
||||
try {
|
||||
plan = typeof response === "string" ? JSON.parse(response) : response;
|
||||
} catch (e) {
|
||||
throw new Error("Invalid JSON from AI: " + e.message);
|
||||
}
|
||||
|
||||
// Validate structure
|
||||
if (!Array.isArray(plan.merges)) plan.merges = [];
|
||||
if (!Array.isArray(plan.updates)) plan.updates = [];
|
||||
|
||||
// Self-merge check: target.id cannot be in sourceTagIds
|
||||
for (const merge of plan.merges) {
|
||||
if (merge.target.id && merge.sourceTagIds.includes(merge.target.id)) {
|
||||
throw new Error("Self-merge detected: " + merge.target.id);
|
||||
}
|
||||
}
|
||||
|
||||
return [{ json: plan }];
|
||||
```
|
||||
|
||||
### 6. HTTP Request - Execute Maintenance
|
||||
|
||||
- Method: POST
|
||||
- URL: `{{$env.SITE_BASE_URL}}/api/tags/maintenance`
|
||||
- Body:
|
||||
|
||||
```json
|
||||
{
|
||||
"apiKey": "{{$env.WEBHOOK_API_KEY}}",
|
||||
"updates": {{$json.updates}},
|
||||
"merges": {{$json.merges}}
|
||||
}
|
||||
```
|
||||
|
||||
### 7. Notification (Slack/Email/Webhook)
|
||||
|
||||
Send summary:
|
||||
|
||||
- Tags merged: X
|
||||
- Tags deleted: Y
|
||||
- Names updated: Z
|
||||
- Errors: [list]
|
||||
|
||||
## Environment Variables Required
|
||||
|
||||
- `SITE_BASE_URL`: https://your-site.com
|
||||
- `WEBHOOK_API_KEY`: API key for authentication
|
||||
|
||||
## Chunking Strategy (for >200 tags)
|
||||
|
||||
1. Split tags into batches of 100
|
||||
2. Process each batch sequentially
|
||||
3. Aggregate results before final notification
|
||||
|
||||
## Error Handling
|
||||
|
||||
- Retry HTTP requests 3x with exponential backoff
|
||||
- On AI parse failure: skip and alert
|
||||
- On maintenance failure: log error, continue with notification
|
||||
|
||||
## Testing
|
||||
|
||||
1. Dry run: Comment out HTTP POST node, check AI output only
|
||||
2. Real run: Enable all nodes, monitor /api/tags count before/after
|
||||
@@ -1,121 +0,0 @@
|
||||
# Frontier Signals Workflow
|
||||
|
||||
## Goal
|
||||
|
||||
Aggregate frontier discussions from multiple platforms, keep only **AI Agent-related** signals via AI filtering, and ingest into `POST /api/webhook/signals`.
|
||||
|
||||
## Workflow
|
||||
|
||||
- Workflow name: `前沿信号聚合(多源+AI Agent过滤)`
|
||||
- Workflow ID: `bAxNZKGq2ApUUiw9`
|
||||
- Status: `active`
|
||||
- Trigger: every 4 hours (`Schedule Trigger`)
|
||||
- Activated at: `2026-02-23`
|
||||
|
||||
## Source Research (Endpoints + Extracted Elements)
|
||||
|
||||
| Source | Endpoint | Node Type | Extracted Elements |
|
||||
| --- | --- | --- | --- |
|
||||
| Hacker News | `https://hacker-news.firebaseio.com/v0/topstories.json` + `.../item/{id}.json` | HTTP Request | `title`, `url`, `text`, `score`, `descendants`, `time` |
|
||||
| GitHub | `https://api.github.com/search/issues` | HTTP Request | `title`, `html_url`, `body`, `comments`, `reactions`, `labels`, `updated_at` |
|
||||
| arXiv | `https://export.arxiv.org/api/query?...` | RSS Read | `title`, `link`, `content/contentSnippet`, `pubDate/isoDate`, `categories` |
|
||||
| Reddit | `https://www.reddit.com/r/LocalLLaMA/new.json?limit=40` | HTTP Request | `title`, `permalink`, `selftext/url`, `ups`, `num_comments`, `created_utc` |
|
||||
| Product Hunt | `https://www.producthunt.com/feed` | RSS Read | `title`, `link`, `content/contentSnippet`, `published/updated` |
|
||||
| Hugging Face | `https://huggingface.co/blog/feed.xml` | RSS Read | `title`, `link`, `content/contentSnippet`, `published/updated` |
|
||||
|
||||
## Why These Nodes
|
||||
|
||||
- `Schedule Trigger`: periodic ingestion
|
||||
- `HTTP Request` / `RSS Read`: source fetching with stable machine-readable endpoints
|
||||
- `Code`: per-source normalization and schema-safe cleanup
|
||||
- `Merge (append)`: multi-source union
|
||||
- `Remove Duplicates`: `source + sourceUrl` dedupe before/after AI
|
||||
- `Limit`: cap candidate volume before AI
|
||||
- `LLM Chain + Structured Output Parser`: relevance filtering + structured sections
|
||||
- `If`: keep only `shouldKeep=true`
|
||||
- `HTTP Request` (POST): write to `/api/webhook/signals`
|
||||
|
||||
## Target Contract Mapping
|
||||
|
||||
The workflow emits payload compatible with `SignalWebhookPayloadSchema`:
|
||||
|
||||
- `apiKey`: manually configured in node `构建 Webhook Payload`
|
||||
- `signals[]`:
|
||||
- `source` -> one of:
|
||||
- `hacker_news`
|
||||
- `github`
|
||||
- `arxiv`
|
||||
- `hugging_face`
|
||||
- `reddit`
|
||||
- `product_hunt`
|
||||
- `sourceUrl`, `title`, `summary`, `topic`, `tags`, `sections`, `engagement`, `hotScore`, `isHot`, `publishedAt`, `isActive`
|
||||
|
||||
Sections are constrained to:
|
||||
|
||||
- style: `focus | debate | evidence | action | risk`
|
||||
- max 6 sections, max 6 items per section
|
||||
|
||||
## AI Filtering Policy
|
||||
|
||||
The AI node does **not** score ideas by novelty/reliability/feasibility.
|
||||
It only decides whether a signal is about AI Agent topics and then structures content for reading efficiency.
|
||||
|
||||
- Keep (`shouldKeep=true`) if discussion is materially agent-related
|
||||
- Drop (`shouldKeep=false`) if clearly unrelated to AI Agent
|
||||
- Drop low-discussion or low-value question items (`shouldKeep=false`)
|
||||
- If information is insufficient, default to drop
|
||||
|
||||
## High-Heat Gate(AI 前硬过滤)
|
||||
|
||||
`筛掉占位候选` 节点会在 AI 前做硬性筛选,减少低价值输入:
|
||||
|
||||
- source-level minimum engagement:
|
||||
- `hacker_news >= 35`
|
||||
- `github >= 8`
|
||||
- `reddit >= 25`
|
||||
- source-level freshness window:
|
||||
- `hacker_news <= 72h`
|
||||
- `github <= 168h`
|
||||
- `reddit/arxiv/hugging_face/product_hunt <= 120h`
|
||||
- low-value question filtering:
|
||||
- 求助型单问题 + 短摘要 + 低互动,直接丢弃
|
||||
- per-source candidate cap(AI 前限流):
|
||||
- `hacker_news 6`, `github 6`, `reddit 6`, `arxiv 4`, `hugging_face 4`, `product_hunt 4`
|
||||
- strict keyword gate for low-discussion sources:
|
||||
- `arxiv/hugging_face/product_hunt` 必须命中 agent 相关关键词(如 `agent`, `agentic`, `multi-agent`, `tool calling`, `mcp`, `智能体`)才进入 AI
|
||||
|
||||
## HOT 判定(流程内)
|
||||
|
||||
`清洗并映射入库字段` Code 节点会基于**互动量 + 时间新鲜度**计算:
|
||||
|
||||
- `hotScore`:0-100
|
||||
- `isHot`:布尔值,用于页面 HOT 标签与排序优先
|
||||
|
||||
该判定只衡量讨论热度,不评价观点对错或质量。
|
||||
|
||||
## DB 升级(新增 HOT 字段)
|
||||
|
||||
由于当前仓库默认忽略 `prisma/migrations/*_*` 目录,建议在数据库手动执行一次:
|
||||
|
||||
```sql
|
||||
ALTER TABLE "signals"
|
||||
ADD COLUMN IF NOT EXISTS "hotScore" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "isHot" BOOLEAN NOT NULL DEFAULT false;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "idx_signal_hot_score" ON "signals"("hotScore");
|
||||
CREATE INDEX IF NOT EXISTS "idx_signal_active_hot_sort" ON "signals"("isActive", "isHot", "hotScore", "publishedAt");
|
||||
```
|
||||
|
||||
## Manual Configuration (No Env)
|
||||
|
||||
This workflow is intentionally configured without `$env` usage.
|
||||
|
||||
- Node `构建 Webhook Payload`:
|
||||
- set `apiKey` to your real webhook key (replace placeholder string)
|
||||
- Node `发送到 Signals Webhook`:
|
||||
- set the target URL to your actual API base (current default is `https://agentpark.fun/api/webhook/signals`)
|
||||
|
||||
## Notes
|
||||
|
||||
- Reddit source uses JSON API with explicit `User-Agent` headers to reduce 403 blocking risk.
|
||||
- `n8n_test_workflow` cannot trigger schedule-only workflows via API; runtime verification should be done by waiting for scheduled execution or manual run in n8n UI.
|
||||
@@ -1,177 +0,0 @@
|
||||
# n8n 历史数据初始化 Workflow
|
||||
|
||||
## 概述
|
||||
|
||||
此 workflow 用于一次性收集和初始化 2017-2025 年的 AI 重大事件数据。
|
||||
|
||||
## Workflow 结构
|
||||
|
||||
### Node 1: Cron 触发器(手动触发)
|
||||
|
||||
- 节点类型: `Manual Trigger`
|
||||
- 用途: 开发测试时手动运行
|
||||
|
||||
### Node 2: 设置年份列表
|
||||
|
||||
- 节点类型: `Code`
|
||||
- 用途: 定义要处理的年份列表
|
||||
|
||||
```javascript
|
||||
// 返回年份数组
|
||||
return [
|
||||
{ year: 2017 },
|
||||
{ year: 2018 },
|
||||
{ year: 2019 },
|
||||
{ year: 2020 },
|
||||
{ year: 2021 },
|
||||
{ year: 2022 },
|
||||
{ year: 2023 },
|
||||
{ year: 2024 },
|
||||
{ year: 2025 },
|
||||
];
|
||||
```
|
||||
|
||||
### Node 3: 搜索 Agent(循环每年)
|
||||
|
||||
- 节点类型: `Loop Over Items`
|
||||
- 用途: 遍历每个年份
|
||||
|
||||
### Node 4: Web Search - Agent 1
|
||||
|
||||
- 节点类型: `HTTP Request`
|
||||
- 方法: POST
|
||||
- URL: `http://localhost:3000/api/web-search` (或 MCP 端点)
|
||||
- Headers:
|
||||
```json
|
||||
{
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
```
|
||||
- Body:
|
||||
```json
|
||||
{
|
||||
"search_query": "AI breakthrough {{ $json.year }} LLM release transformer model",
|
||||
"search_recency_filter": "noLimit",
|
||||
"content_size": "high"
|
||||
}
|
||||
```
|
||||
|
||||
### Node 5: 筛选 Agent - Agent 2
|
||||
|
||||
- 节点类型: `Code`
|
||||
- 用途: 根据权威来源筛选
|
||||
|
||||
```javascript
|
||||
const trustedDomains = [
|
||||
'arxiv.org',
|
||||
'openai.com',
|
||||
'anthropic.com',
|
||||
'google.ai',
|
||||
'meta.ai',
|
||||
'deepmind.com',
|
||||
'research.google',
|
||||
];
|
||||
|
||||
const items = $input.all();
|
||||
|
||||
const filtered = items.filter(item => {
|
||||
const url = item.json.url || '';
|
||||
return trustedDomains.some(domain => url.includes(domain));
|
||||
});
|
||||
|
||||
return filtered;
|
||||
```
|
||||
|
||||
### Node 6: 格式化 Agent - Agent 3
|
||||
|
||||
- 节点类型: `Code`
|
||||
- 用途: 转换为 API 格式
|
||||
|
||||
```javascript
|
||||
const items = $input.all();
|
||||
|
||||
const formatted = items.map(item => {
|
||||
const publishedDate = item.json.published_date || new Date().toISOString();
|
||||
|
||||
return {
|
||||
json: {
|
||||
title: item.json.title || 'Untitled',
|
||||
eventDate: new Date(publishedDate).toISOString(),
|
||||
description: (item.json.description || item.json.snippet || '').substring(0, 500),
|
||||
imageUrl: item.json.image_url || 'https://images.unsplash.com/photo-1677442136019-21780ecad995?w=800',
|
||||
sourceUrl: item.json.url,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
return formatted;
|
||||
```
|
||||
|
||||
### Node 7: 提交到 API
|
||||
|
||||
- 节点类型: `HTTP Request`
|
||||
- 方法: POST
|
||||
- URL: `http://localhost:3000/api/events`
|
||||
- Headers:
|
||||
```json
|
||||
{
|
||||
"Content-Type": "application/json",
|
||||
"X-API-Key": "={{ $env.WEBHOOK_API_KEY }}"
|
||||
}
|
||||
```
|
||||
- Body: `={{ $json }}` (发送整个数组)
|
||||
|
||||
### Node 8: 错误处理
|
||||
|
||||
- 节点类型: `IF`
|
||||
- 条件: 检查上一个节点的 status code
|
||||
- On True: 记录成功
|
||||
- On False: 发送错误邮件
|
||||
|
||||
## 环境变量
|
||||
|
||||
在 n8n 中设置:
|
||||
- `WEBHOOK_API_KEY`: 你的 API 密钥(从 .env.local 获取)
|
||||
- `API_ENDPOINT`: `http://localhost:3000/api/events` (开发) 或生产 URL
|
||||
|
||||
## 测试步骤
|
||||
|
||||
1. 在 n8n UI 中创建此 workflow
|
||||
2. 手动触发运行
|
||||
3. 检查数据库: `pnpm prisma studio`
|
||||
4. 验证事件已正确创建
|
||||
|
||||
## 数据质量标准
|
||||
|
||||
### 标题要求
|
||||
- 清晰描述事件
|
||||
- 1-200 字符
|
||||
- 避免营销术语
|
||||
|
||||
### 描述要求
|
||||
- 客观描述功能和价值
|
||||
- 10-500 字符
|
||||
- 突出技术亮点
|
||||
|
||||
### 日期要求
|
||||
- ISO 8601 格式
|
||||
- 准确的发布日期
|
||||
|
||||
### 链接要求
|
||||
- 必须包含 sourceUrl(权威来源)
|
||||
- 链接可访问
|
||||
- 优先 arxiv.org、openai.com 等
|
||||
|
||||
## 权威来源列表
|
||||
|
||||
- 学术论文: arxiv.org
|
||||
- 官方博客: openai.com, anthropic.com, google.ai, meta.ai
|
||||
- 研究机构: deepmind.com, research.google
|
||||
- 新闻媒体: techcrunch.com, theverge.com (需人工审核)
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **去重**: workflow 会自动跳过重复的事件(基于 sourceUrl)
|
||||
2. **图片**: 如果没有图片,使用默认占位图
|
||||
3. **错误处理**: 失败的事件会被记录,不会中断整个流程
|
||||
4. **数据验证**: API 会验证所有字段,不符合标准的数据会被拒绝
|
||||
@@ -1,135 +0,0 @@
|
||||
# n8n 增量更新 Workflow
|
||||
|
||||
## 概述
|
||||
|
||||
此 workflow 每周一自动运行,收集最近 7 天的新 AI 事件。
|
||||
|
||||
## Workflow 结构
|
||||
|
||||
### Node 1: Cron 触发器
|
||||
|
||||
- 节点类型: `Cron`
|
||||
- 表达式: `0 9 * * 1` (每周一早上 9:00)
|
||||
- 时区: Asia/Shanghai
|
||||
|
||||
### Node 2: Web Search - Agent 1
|
||||
|
||||
- 节点类型: `HTTP Request`
|
||||
- URL: `http://localhost:3000/api/web-search` (或 MCP 端点)
|
||||
- Body:
|
||||
```json
|
||||
{
|
||||
"search_query": "AI news LLM release model launch this week",
|
||||
"search_recency_filter": "oneWeek"
|
||||
}
|
||||
```
|
||||
|
||||
### Node 3: 筛选 Agent - Agent 2
|
||||
|
||||
- 节点类型: `Code`
|
||||
- 用途: 筛选 + 去重(查询数据库避免重复)
|
||||
|
||||
```javascript
|
||||
const trustedDomains = [
|
||||
'arxiv.org',
|
||||
'openai.com',
|
||||
'anthropic.com',
|
||||
'google.ai',
|
||||
'meta.ai',
|
||||
'deepmind.com',
|
||||
];
|
||||
|
||||
// 过滤权威来源
|
||||
const items = $input.all();
|
||||
const filtered = items.filter(item => {
|
||||
const url = item.json.url || '';
|
||||
return trustedDomains.some(domain => url.includes(domain));
|
||||
});
|
||||
|
||||
// TODO: 添加数据库查询去重
|
||||
// 这里可以调用 GET /api/events 检查 sourceUrl 是否已存在
|
||||
|
||||
return filtered;
|
||||
```
|
||||
|
||||
### Node 4: 格式化 Agent - Agent 3
|
||||
|
||||
- 节点类型: `Code`
|
||||
- 代码: 同历史 workflow
|
||||
|
||||
### Node 5: 提交到 API
|
||||
|
||||
- 节点类型: `HTTP Request`
|
||||
- 配置: 同历史 workflow
|
||||
|
||||
### Node 6: 发送通知邮件
|
||||
|
||||
- 节点类型: `Send Email`
|
||||
- 条件: 仅在创建新事件时发送
|
||||
- 内容:
|
||||
```
|
||||
主题: AI Timeline - 新事件已添加
|
||||
|
||||
本次更新添加了 {{ $json.created }} 个新事件。
|
||||
|
||||
查看: https://your-domain.com/timeline
|
||||
```
|
||||
|
||||
### Node 7: 错误处理
|
||||
|
||||
- 节点类型: `Error Trigger`
|
||||
- 动作: 发送错误邮件到管理员
|
||||
|
||||
## 测试
|
||||
|
||||
1. 修改 Cron 为手动触发进行测试
|
||||
2. 验证只有新事件被添加
|
||||
3. 检查邮件通知是否正常发送
|
||||
4. 确认错误处理工作正常
|
||||
|
||||
## 数据质量保证
|
||||
|
||||
### 自动筛选规则
|
||||
|
||||
1. **来源可信**: 仅来自权威域名
|
||||
2. **时效性**: 仅最近 7 天的内容
|
||||
3. **去重**: 基于 sourceUrl 自动去重
|
||||
|
||||
### 人工审核流程
|
||||
|
||||
建议在自动导入后进行人工审核:
|
||||
1. 检查标题是否准确
|
||||
2. 验证描述是否客观
|
||||
3. 确认图片是否合适
|
||||
4. 测试链接是否可访问
|
||||
|
||||
## 邮件通知配置
|
||||
|
||||
### 成功通知
|
||||
|
||||
当有新事件添加时发送:
|
||||
- 收件人: 内容团队
|
||||
- 主题: "AI Timeline - {{ count }} 个新事件已添加"
|
||||
- 内容: 包含事件列表和链接
|
||||
|
||||
### 错误通知
|
||||
|
||||
当 workflow 失败时发送:
|
||||
- 收件人: 技术团队
|
||||
- 主题: "⚠️ AI Timeline Workflow 失败"
|
||||
- 内容: 错误详情和日志
|
||||
|
||||
## 监控指标
|
||||
|
||||
建议监控以下指标:
|
||||
- 每周添加的事件数量
|
||||
- workflow 执行时间
|
||||
- 失败率和错误类型
|
||||
- 去重率
|
||||
|
||||
## 优化建议
|
||||
|
||||
1. **AI 辅助筛选**: 使用 AI 模型评估新闻相关性
|
||||
2. **多源聚合**: 整合多个搜索 API
|
||||
3. **智能去重**: 基于标题相似度去重
|
||||
4. **自动翻译**: 自动生成英文翻译(titleEn, descriptionEn)
|
||||
@@ -1,435 +0,0 @@
|
||||
{
|
||||
"name": "Project Tag Reset - Multi AI Classifier",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "manual-trigger",
|
||||
"name": "手动触发",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "https://www.agentpark.fun/api/tags",
|
||||
"options": {}
|
||||
},
|
||||
"id": "fetch-tags",
|
||||
"name": "获取标签池",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.4,
|
||||
"position": [
|
||||
220,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "https://www.agentpark.fun/api/projects",
|
||||
"sendQuery": true,
|
||||
"specifyQuery": "keypair",
|
||||
"queryParameters": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "limit",
|
||||
"value": "100"
|
||||
},
|
||||
{
|
||||
"name": "page",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"name": "sort",
|
||||
"value": "latest"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"pagination": {
|
||||
"pagination": {
|
||||
"paginationMode": "updateAParameterInEachRequest",
|
||||
"parameters": {
|
||||
"parameters": [
|
||||
{
|
||||
"type": "qs",
|
||||
"name": "page",
|
||||
"value": "={{($response.body.pagination.page ?? $response.body.pagination.currentPage ?? 1) + 1}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"paginationCompleteWhen": "other",
|
||||
"completeExpression": "={{!$response.body.pagination || (($response.body.pagination.page ?? $response.body.pagination.currentPage ?? 1) >= ($response.body.pagination.totalPages ?? 1))}}",
|
||||
"limitPagesFetched": true,
|
||||
"maxRequests": 20,
|
||||
"requestInterval": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "fetch-projects",
|
||||
"name": "获取项目列表",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.4,
|
||||
"position": [
|
||||
440,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const tagsResponse = $('获取标签池').first().json;\nconst project = $input.first().json.projects;\n\nif (!tagsResponse?.success || !Array.isArray(tagsResponse?.tags)) {\n throw new Error('Failed to fetch tags from /api/tags');\n}\n\nif (!project || typeof project !== 'object' || !project.slug) {\n throw new Error('Invalid project item after split');\n}\n\nconst allowedCategories = [\n 'FIXED_PROJECT_TYPE',\n 'TECH_STACK',\n 'AI_PARADIGM',\n 'PRODUCT_FORM',\n 'DOMAIN_SCENARIO',\n];\n\nconst tagPools = Object.fromEntries(\n allowedCategories.map((category) => [\n category,\n tagsResponse.tags\n .filter((tag) => tag.category === category)\n .map((tag) => ({\n id: tag.id,\n slug: tag.slug,\n name: tag.name,\n nameEn: tag.nameEn || '',\n })),\n ])\n);\n\nreturn [\n {\n json: {\n projectSlug: project.slug,\n projectName: project.name,\n projectNameEn: project.nameEn || '',\n projectDescription: project.description,\n projectDescriptionEn: project.descriptionEn || '',\n currentTags: Array.isArray(project.tags)\n ? project.tags.map((tag) => ({\n slug: tag.slug,\n name: tag.name,\n nameEn: tag.nameEn || '',\n }))\n : [],\n tagPools,\n },\n },\n];"
|
||||
},
|
||||
"id": "prepare-classification-items",
|
||||
"name": "准备分类输入",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
660,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"model": "gpt-4o-mini",
|
||||
"messages": {
|
||||
"values": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You classify projects into FIXED_PROJECT_TYPE. Return STRICT JSON only."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "=Project:\\n- slug: {{$json.projectSlug}}\\n- name: {{$json.projectName}}\\n- nameEn: {{$json.projectNameEn}}\\n- description: {{$json.projectDescription}}\\n- descriptionEn: {{$json.projectDescriptionEn}}\\n- currentTags: {{JSON.stringify($json.currentTags)}}\\n\\nCandidate pool (FIXED_PROJECT_TYPE):\\n{{JSON.stringify($json.tagPools.FIXED_PROJECT_TYPE)}}\\n\\nTask:\\n- Choose exactly ONE best slug from candidate pool.\\n\\nOutput strict JSON only:\\n{\\n \"selected\": [\"one-slug\"]\\n}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"temperature": 0.1
|
||||
}
|
||||
},
|
||||
"id": "ai-fixed-project-type",
|
||||
"name": "AI 固定项目分类",
|
||||
"type": "@n8n/n8n-nodes-langchain.openAi",
|
||||
"typeVersion": 1.8,
|
||||
"position": [
|
||||
880,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"model": "gpt-4o-mini",
|
||||
"messages": {
|
||||
"values": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You classify DOMAIN_SCENARIO tags. Return STRICT JSON only."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "=Project:\\n- slug: {{$json.projectSlug}}\\n- name: {{$json.projectName}}\\n- description: {{$json.projectDescription}}\\n- currentTags: {{JSON.stringify($json.currentTags)}}\\n\\nCandidate pool (DOMAIN_SCENARIO):\\n{{JSON.stringify($json.tagPools.DOMAIN_SCENARIO)}}\\n\\nTask:\\n- Choose 1 to 3 slugs from candidate pool.\\n- Keep only the most representative domains for this project.\\n\\nOutput strict JSON only:\\n{\\n \"selected\": [\"slug1\", \"slug2\"]\\n}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"temperature": 0.1
|
||||
}
|
||||
},
|
||||
"id": "ai-domain-scenario",
|
||||
"name": "AI 领域场景分类",
|
||||
"type": "@n8n/n8n-nodes-langchain.openAi",
|
||||
"typeVersion": 1.8,
|
||||
"position": [
|
||||
1100,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"model": "gpt-4o-mini",
|
||||
"messages": {
|
||||
"values": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You classify PRODUCT_FORM tags. Return STRICT JSON only."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "=Project:\\n- slug: {{$json.projectSlug}}\\n- name: {{$json.projectName}}\\n- description: {{$json.projectDescription}}\\n- currentTags: {{JSON.stringify($json.currentTags)}}\\n\\nCandidate pool (PRODUCT_FORM):\\n{{JSON.stringify($json.tagPools.PRODUCT_FORM)}}\\n\\nTask:\\n- Choose 1 to 3 slugs from candidate pool that best represent product form.\\n\\nOutput strict JSON only:\\n{\\n \"selected\": [\"slug1\", \"slug2\"]\\n}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"temperature": 0.1
|
||||
}
|
||||
},
|
||||
"id": "ai-product-form",
|
||||
"name": "AI 产品形态分类",
|
||||
"type": "@n8n/n8n-nodes-langchain.openAi",
|
||||
"typeVersion": 1.8,
|
||||
"position": [
|
||||
1320,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"model": "gpt-4o-mini",
|
||||
"messages": {
|
||||
"values": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You classify TECH_STACK tags. Return STRICT JSON only."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "=Project:\\n- slug: {{$json.projectSlug}}\\n- name: {{$json.projectName}}\\n- description: {{$json.projectDescription}}\\n- currentTags: {{JSON.stringify($json.currentTags)}}\\n\\nCandidate pool (TECH_STACK):\\n{{JSON.stringify($json.tagPools.TECH_STACK)}}\\n\\nTask:\\n- Choose 1 to 8 slugs from candidate pool for the main technologies used by this project.\\n\\nOutput strict JSON only:\\n{\\n \"selected\": [\"slug1\", \"slug2\"]\\n}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"temperature": 0.1
|
||||
}
|
||||
},
|
||||
"id": "ai-tech-stack",
|
||||
"name": "AI 技术栈分类",
|
||||
"type": "@n8n/n8n-nodes-langchain.openAi",
|
||||
"typeVersion": 1.8,
|
||||
"position": [
|
||||
1540,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"model": "gpt-4o-mini",
|
||||
"messages": {
|
||||
"values": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You classify AI_PARADIGM tags. Return STRICT JSON only."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "=Project:\\n- slug: {{$json.projectSlug}}\\n- name: {{$json.projectName}}\\n- description: {{$json.projectDescription}}\\n- currentTags: {{JSON.stringify($json.currentTags)}}\\n\\nCandidate pool (AI_PARADIGM):\\n{{JSON.stringify($json.tagPools.AI_PARADIGM)}}\\n\\nTask:\\n- Choose 0 to 5 slugs from candidate pool for AI paradigm.\\n\\nOutput strict JSON only:\\n{\\n \"selected\": [\"slug1\", \"slug2\"]\\n}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"temperature": 0.1
|
||||
}
|
||||
},
|
||||
"id": "ai-ai-paradigm",
|
||||
"name": "AI 技术范式分类",
|
||||
"type": "@n8n/n8n-nodes-langchain.openAi",
|
||||
"typeVersion": 1.8,
|
||||
"position": [
|
||||
1760,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "function parseNodeJson(nodeJson) {\n const content = nodeJson?.message?.content || nodeJson?.text || nodeJson?.response || nodeJson;\n\n if (typeof content === 'string') {\n const trimmed = content.trim();\n try {\n return JSON.parse(trimmed);\n } catch {\n const jsonMatch = trimmed.match(/\\{[\\s\\S]*\\}/);\n if (jsonMatch) {\n return JSON.parse(jsonMatch[0]);\n }\n return { selected: [] };\n }\n }\n\n if (typeof content === 'object' && content !== null) {\n return content;\n }\n\n return { selected: [] };\n}\n\nfunction normalizeSelected(parsed, pool, minCount, maxCount) {\n const poolSlugs = pool.map((tag) => String(tag.slug).toLowerCase());\n const allowed = new Set(poolSlugs);\n const selectedRaw = Array.isArray(parsed?.selected) ? parsed.selected : [];\n const selected = [];\n\n for (const slug of selectedRaw) {\n const normalizedSlug = String(slug || '').trim().toLowerCase();\n if (!normalizedSlug || !allowed.has(normalizedSlug) || selected.includes(normalizedSlug)) {\n continue;\n }\n selected.push(normalizedSlug);\n if (selected.length >= maxCount) {\n break;\n }\n }\n\n if (selected.length < minCount) {\n return poolSlugs.slice(0, minCount);\n }\n return selected;\n}\n\nconst preparedItems = $items('准备分类输入', 0);\nconst fixedItems = $items('AI 固定项目分类', 0);\nconst domainItems = $items('AI 领域场景分类', 0);\nconst productItems = $items('AI 产品形态分类', 0);\nconst techItems = $items('AI 技术栈分类', 0);\nconst paradigmItems = $items('AI 技术范式分类', 0);\n\nif (\n preparedItems.length !== fixedItems.length ||\n preparedItems.length !== domainItems.length ||\n preparedItems.length !== productItems.length ||\n preparedItems.length !== techItems.length ||\n preparedItems.length !== paradigmItems.length\n) {\n throw new Error('AI node output item count mismatch');\n}\n\nconst output = [];\nfor (let i = 0; i < preparedItems.length; i++) {\n const base = preparedItems[i].json;\n const pools = base.tagPools;\n\n const fixed = normalizeSelected(\n parseNodeJson(fixedItems[i].json),\n pools.FIXED_PROJECT_TYPE,\n 1,\n 1\n );\n const domains = normalizeSelected(\n parseNodeJson(domainItems[i].json),\n pools.DOMAIN_SCENARIO,\n 1,\n 3\n );\n const productForms = normalizeSelected(\n parseNodeJson(productItems[i].json),\n pools.PRODUCT_FORM,\n 1,\n 3\n );\n const techStack = normalizeSelected(\n parseNodeJson(techItems[i].json),\n pools.TECH_STACK,\n 1,\n 8\n );\n const paradigms = normalizeSelected(\n parseNodeJson(paradigmItems[i].json),\n pools.AI_PARADIGM,\n 0,\n 5\n );\n\n output.push({\n json: {\n projectSlug: base.projectSlug,\n selectedTagSlugsByCategory: {\n FIXED_PROJECT_TYPE: fixed,\n TECH_STACK: techStack,\n AI_PARADIGM: paradigms,\n PRODUCT_FORM: productForms,\n DOMAIN_SCENARIO: domains,\n },\n },\n });\n}\n\nreturn output;"
|
||||
},
|
||||
"id": "build-reset-payload",
|
||||
"name": "组装重置载荷",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
1980,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"method": "POST",
|
||||
"url": "https://www.agentpark.fun/api/tags/reset-projects",
|
||||
"sendBody": true,
|
||||
"specifyBody": "json",
|
||||
"jsonBody": "={\n \"apiKey\": \"{{$env.WEBHOOK_API_KEY}}\",\n \"dryRun\": false,\n \"replaceAllCategories\": true,\n \"projects\": [\n {\n \"projectSlug\": \"{{$json.projectSlug}}\",\n \"selectedTagSlugsByCategory\": {{JSON.stringify($json.selectedTagSlugsByCategory)}}\n }\n ]\n}",
|
||||
"options": {}
|
||||
},
|
||||
"id": "reset-project-tags",
|
||||
"name": "调用标签重置接口",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.4,
|
||||
"position": [
|
||||
2200,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const results = $input.all().map((item) => item.json);\nconst summary = {\n totalRequests: results.length,\n successRequests: results.filter((r) => r.success === true).length,\n failedRequests: results.filter((r) => r.success !== true).length,\n timestamp: new Date().toISOString(),\n};\n\nreturn [{ json: { summary, results } }];"
|
||||
},
|
||||
"id": "summarize-results",
|
||||
"name": "汇总执行结果",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
2420,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"operation": "splitOutItems",
|
||||
"fieldToSplitOut": "projects",
|
||||
"include": "noOtherFields",
|
||||
"options": {}
|
||||
},
|
||||
"id": "split-projects",
|
||||
"name": "拆分项目列表",
|
||||
"type": "n8n-nodes-base.itemLists",
|
||||
"typeVersion": 3.1,
|
||||
"position": [
|
||||
560,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"connections": {
|
||||
"手动触发": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "获取标签池",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"获取标签池": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "获取项目列表",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"获取项目列表": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "拆分项目列表",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"准备分类输入": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "AI 固定项目分类",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"AI 固定项目分类": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "AI 领域场景分类",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"AI 领域场景分类": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "AI 产品形态分类",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"AI 产品形态分类": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "AI 技术栈分类",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"AI 技术栈分类": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "AI 技术范式分类",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"AI 技术范式分类": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "组装重置载荷",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"组装重置载荷": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "调用标签重置接口",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"调用标签重置接口": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "汇总执行结果",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"拆分项目列表": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "准备分类输入",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": true
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
# Project Tag Reset Workflow
|
||||
|
||||
## Goal
|
||||
|
||||
Reset every project's tags according to the new taxonomy, using **one dedicated AI node per tag category**:
|
||||
|
||||
- `FIXED_PROJECT_TYPE`
|
||||
- `DOMAIN_SCENARIO`
|
||||
- `PRODUCT_FORM`
|
||||
- `TECH_STACK`
|
||||
- `AI_PARADIGM`
|
||||
|
||||
Each AI node must select only from its own category pool.
|
||||
|
||||
## Files
|
||||
|
||||
- Workflow JSON: `docs/n8n/project-tag-reset-workflow.json`
|
||||
- API endpoint used by workflow: `POST /api/tags/reset-projects`
|
||||
|
||||
## Required Environment Variables in n8n
|
||||
|
||||
- `WEBHOOK_API_KEY`: same key configured on Next.js server
|
||||
|
||||
## Fixed Base URL
|
||||
|
||||
- All workflow API URLs are hardcoded to `https://www.agentpark.fun`
|
||||
|
||||
## Execution Flow
|
||||
|
||||
1. `手动触发`
|
||||
2. `获取标签池` (`HTTP GET /api/tags`) 读取标签池
|
||||
3. `获取项目列表` (`HTTP GET /api/projects`) 使用 Query 参数(`limit=100,page=1,sort=latest`)+ HTTP 节点内置分页拉取全部项目
|
||||
4. `拆分项目列表` 将每页 `projects[]` 拆分为“单项目一条记录”
|
||||
5. `准备分类输入` 仅做轻量字段整理(不再负责分页/HTTP 请求)
|
||||
6. 五个独立 AI 节点分别分类:
|
||||
- `AI 固定项目分类`
|
||||
- `AI 领域场景分类`
|
||||
- `AI 产品形态分类`
|
||||
- `AI 技术栈分类`
|
||||
- `AI 技术范式分类`
|
||||
7. `组装重置载荷` 归一化 AI 输出并生成 `selectedTagSlugsByCategory`
|
||||
8. `调用标签重置接口` (`HTTP POST /api/tags/reset-projects`) 回写标签
|
||||
9. `汇总执行结果` 输出成功/失败统计
|
||||
|
||||
## Notes
|
||||
|
||||
- Workflow uses HTTP node built-in pagination for `/api/projects` (`limit=100`) to process full project volume.
|
||||
- `page` 不再写死在 URL 上,避免出现重复请求同一页导致的 identical response 停止问题。
|
||||
- Pagination and project fan-out no longer rely on complex Code-node network logic.
|
||||
- Workflow no longer depends on `SITE_BASE_URL`; base URL is fixed to `https://www.agentpark.fun`.
|
||||
- Endpoint supports `dryRun`. You can set `"dryRun": true` first in the request node for safe validation.
|
||||
- Endpoint performs category validation and rejects cross-category slug usage.
|
||||
@@ -1,151 +0,0 @@
|
||||
{
|
||||
"name": "Tag Janitor - Daily Cleanup",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {
|
||||
"rule": {
|
||||
"interval": [
|
||||
{
|
||||
"triggerAtHour": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"id": "schedule",
|
||||
"name": "Daily 3AM UTC",
|
||||
"type": "n8n-nodes-base.scheduleTrigger",
|
||||
"typeVersion": 1.2,
|
||||
"position": [0, 0]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "={{$env.SITE_BASE_URL}}/api/tags",
|
||||
"options": {}
|
||||
},
|
||||
"id": "fetch-tags",
|
||||
"name": "Fetch Tags",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.2,
|
||||
"position": [220, 0]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const response = $input.first().json;\nif (!response.success) {\n throw new Error('Failed to fetch tags: ' + JSON.stringify(response));\n}\n\nconst tags = response.tags;\nconst formatted = tags.map(t => ({\n id: t.id,\n name: t.name,\n nameEn: t.nameEn || '',\n projectCount: t._count?.projects || 0\n}));\n\n// Sort by project count descending\nformatted.sort((a, b) => b.projectCount - a.projectCount);\n\nreturn [{ json: { tags: formatted, total: formatted.length } }];"
|
||||
},
|
||||
"id": "preprocess",
|
||||
"name": "Preprocess Tags",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [440, 0]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"model": "gpt-4o",
|
||||
"messages": {
|
||||
"values": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You are a tag management expert. Analyze tags and identify semantic duplicates for merging and missing English names for completion. Output STRICT JSON only."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Analyze these tags and identify:\n1. Semantic duplicates to merge (e.g., \"机器学习\" and \"ML\" → keep higher projectCount)\n2. Tags missing nameEn that need English names\n\nTags ({{$json.total}} total):\n{{JSON.stringify($json.tags)}}\n\nOutput STRICT JSON (no markdown):\n{\n \"merges\": [\n {\n \"target\": { \"name\": \"保留的标签\", \"nameEn\": \"Canonical Name\" },\n \"sourceTagIds\": [\"id1\", \"id2\"]\n }\n ],\n \"updates\": [\n { \"tagId\": \"id\", \"nameEn\": \"English Name\" }\n ]\n}\n\nRules:\n- Keep tag with higher projectCount as merge target\n- target can use { \"id\": \"existing\" } to keep existing tag\n- Only include tags needing action (empty arrays if none)\n- nameEn must be proper English, not pinyin"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"temperature": 0.1
|
||||
}
|
||||
},
|
||||
"id": "ai-analyze",
|
||||
"name": "AI Analyze Tags",
|
||||
"type": "@n8n/n8n-nodes-langchain.openAi",
|
||||
"typeVersion": 1.8,
|
||||
"position": [660, 0]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const response = $input.first().json;\nlet plan;\n\ntry {\n const content = response.message?.content || response.text || response;\n plan = typeof content === 'string' ? JSON.parse(content) : content;\n} catch (e) {\n throw new Error('Failed to parse AI response: ' + e.message);\n}\n\nif (!Array.isArray(plan.merges)) plan.merges = [];\nif (!Array.isArray(plan.updates)) plan.updates = [];\n\nfor (const merge of plan.merges) {\n if (merge.target.id && merge.sourceTagIds.includes(merge.target.id)) {\n throw new Error('Self-merge detected: ' + merge.target.id);\n }\n}\n\nif (plan.merges.length === 0 && plan.updates.length === 0) {\n return [{ json: { skipped: true, reason: 'No changes needed' } }];\n}\n\nreturn [{ json: plan }];"
|
||||
},
|
||||
"id": "validate-json",
|
||||
"name": "Validate JSON",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [880, 0]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"conditions": {
|
||||
"boolean": [
|
||||
{
|
||||
"value1": "={{$json.skipped}}",
|
||||
"value2": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"id": "check-skip",
|
||||
"name": "Check Skip",
|
||||
"type": "n8n-nodes-base.if",
|
||||
"typeVersion": 2,
|
||||
"position": [1100, 0]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"method": "POST",
|
||||
"url": "={{$env.SITE_BASE_URL}}/api/tags/maintenance",
|
||||
"sendBody": true,
|
||||
"specifyBody": "json",
|
||||
"jsonBody": "={\n \"apiKey\": \"{{$env.WEBHOOK_API_KEY}}\",\n \"updates\": {{JSON.stringify($json.updates)}},\n \"merges\": {{JSON.stringify($json.merges)}}\n}",
|
||||
"options": {}
|
||||
},
|
||||
"id": "execute-maintenance",
|
||||
"name": "Execute Maintenance",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.2,
|
||||
"position": [1320, -100]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const maintenanceResult = $('Execute Maintenance').first()?.json || {};\nconst skipped = $('Check Skip').first()?.json?.skipped;\n\nif (skipped) {\n return [{ json: {\n status: 'skipped',\n message: 'No changes needed',\n timestamp: new Date().toISOString()\n }}];\n}\n\nconst result = maintenanceResult.result || {};\n\nreturn [{ json: {\n status: maintenanceResult.success ? 'success' : 'failed',\n updatedCount: result.updatedCount || 0,\n mergedCount: result.mergedCount || 0,\n deletedTagCount: result.deletedTagCount || 0,\n timestamp: new Date().toISOString(),\n error: maintenanceResult.error || null\n}}];"
|
||||
},
|
||||
"id": "summarize",
|
||||
"name": "Summarize Results",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [1540, 0]
|
||||
}
|
||||
],
|
||||
"connections": {
|
||||
"Daily 3AM UTC": {
|
||||
"main": [[{ "node": "Fetch Tags", "type": "main", "index": 0 }]]
|
||||
},
|
||||
"Fetch Tags": {
|
||||
"main": [[{ "node": "Preprocess Tags", "type": "main", "index": 0 }]]
|
||||
},
|
||||
"Preprocess Tags": {
|
||||
"main": [[{ "node": "AI Analyze Tags", "type": "main", "index": 0 }]]
|
||||
},
|
||||
"AI Analyze Tags": {
|
||||
"main": [[{ "node": "Validate JSON", "type": "main", "index": 0 }]]
|
||||
},
|
||||
"Validate JSON": {
|
||||
"main": [[{ "node": "Check Skip", "type": "main", "index": 0 }]]
|
||||
},
|
||||
"Check Skip": {
|
||||
"main": [
|
||||
[{ "node": "Execute Maintenance", "type": "main", "index": 0 }],
|
||||
[{ "node": "Summarize Results", "type": "main", "index": 0 }]
|
||||
]
|
||||
},
|
||||
"Execute Maintenance": {
|
||||
"main": [[{ "node": "Summarize Results", "type": "main", "index": 0 }]]
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user