Unified · Split
| @@ -2,364 +2,314 @@ · 1 unmodified line | ||
| 2 | 2 | import Layout from '../layouts/Layout.astro' |
| 3 | 3 | --- |
| 4 | 4 | |
| 5 | −<Layout title="Executor — The unified tool catalog for AI agents" description="Stop making everyone on your team set up their own agent integrations. Connect your services to Executor once, and give every agent in your organization safe, authenticated access to your entire stack."> | |
| 6 | − <main class="bg-zinc-950 text-zinc-50 min-h-screen selection:bg-zinc-800 selection:text-white"> | |
| 5 | +<Layout title="Executor | Unified Catalog" description="Connect your services once, give every agent authenticated access to your stack."> | |
| 6 | + <main class="bg-white min-h-screen text-slate-800 font-sans selection:bg-blue-200 selection:text-blue-900 pb-32 overflow-hidden relative"> | |
| 7 | 7 | |
| 8 | − {/* NAVIGATION */} | |
| 9 | − <nav class="fixed top-0 inset-x-0 z-50 bg-zinc-950/80 backdrop-blur-md border-b border-zinc-900"> | |
| 10 | − <div class="max-w-6xl mx-auto px-6 h-16 flex items-center justify-between"> | |
| 11 | − <div class="flex items-center gap-2 font-mono font-semibold text-lg tracking-tight"> | |
| 12 | − <div class="w-5 h-5 rounded bg-white"></div> | |
| 8 | + {/* Architectural Blueprint Background */} | |
| 9 | + <div class="absolute inset-0 bg-[linear-gradient(#e2e8f0_1px,transparent_1px),linear-gradient(90deg,#e2e8f0_1px,transparent_1px)] bg-[size:32px_32px] pointer-events-none opacity-50"></div> | |
| 10 | + | |
| 11 | + {/* TOP BAR */} | |
| 12 | + <nav class="fixed top-0 w-full bg-white/90 backdrop-blur-md border-b border-slate-200 z-50"> | |
| 13 | + <div class="max-w-7xl mx-auto px-6 h-16 flex items-center justify-between"> | |
| 14 | + <div class="flex items-center gap-2 font-bold text-slate-900 tracking-tight"> | |
| 15 | + <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="text-blue-600"><rect x="2" y="4" width="20" height="16" rx="2"></rect><path d="M10 4v4"></path><path d="M2 8h20"></path><path d="M6 4v4"></path></svg> | |
| 13 | 16 | Executor |
| 14 | 17 | </div> |
| 15 | − <div class="hidden md:flex items-center gap-8 text-sm font-medium text-zinc-400"> | |
| 16 | − <a href="/docs" class="hover:text-white transition-colors">Docs</a> | |
| 17 | − <a href="/pricing" class="hover:text-white transition-colors">Pricing</a> | |
| 18 | − <a href="https://github.com/executor-js/executor" class="hover:text-white transition-colors">GitHub ⭐</a> | |
| 18 | + <div class="hidden md:flex items-center gap-8 text-sm font-semibold text-slate-600"> | |
| 19 | + <a href="/docs" class="hover:text-blue-600 transition-colors">Documentation</a> | |
| 20 | + <a href="/pricing" class="hover:text-blue-600 transition-colors">Pricing</a> | |
| 21 | + <a href="https://github.com/executor-js/executor" class="hover:text-blue-600 transition-colors">GitHub</a> | |
| 19 | 22 | </div> |
| 20 | 23 | <div class="flex items-center gap-4"> |
| 21 | − <a href="/docs" class="bg-white text-black px-4 py-2 rounded-md text-sm font-semibold hover:bg-zinc-200 transition-colors">Get Started</a> | |
| 24 | + <a href="/docs" class="bg-blue-600 text-white px-5 py-2 rounded-md text-sm font-semibold hover:bg-blue-700 transition-colors shadow-sm"> | |
| 25 | + Get Started | |
| 26 | + </a> | |
| 22 | 27 | </div> |
| 23 | 28 | </div> |
| 24 | 29 | </nav> |
| 25 | 30 | |
| 26 | − {/* 1. THE HERO */} | |
| 27 | − <section class="pt-40 pb-20 px-6 overflow-hidden"> | |
| 28 | − <div class="max-w-4xl mx-auto text-center"> | |
| 29 | − <h1 class="text-5xl md:text-7xl font-bold tracking-tight mb-8 font-serif"> | |
| 30 | − The unified tool catalog <br class="hidden md:block"/> for AI agents. | |
| 31 | − </h1> | |
| 32 | − <p class="text-xl md:text-2xl text-zinc-400 max-w-3xl mx-auto leading-relaxed font-sans mb-12"> | |
| 33 | − Stop making everyone on your team set up their own agent integrations. Connect your services to Executor once, and give every agent in your organization safe, authenticated access to your entire stack. | |
| 34 | − </p> | |
| 35 | − <div class="flex flex-col sm:flex-row items-center justify-center gap-4"> | |
| 36 | − <a href="/docs" class="bg-white text-black px-8 py-3 rounded-lg text-base font-semibold hover:bg-zinc-200 transition-colors w-full sm:w-auto"> | |
| 37 | − Get Started | |
| 38 | − </a> | |
| 39 | − <div class="flex items-center bg-zinc-900 border border-zinc-800 px-6 py-3 rounded-lg text-zinc-300 font-mono text-sm w-full sm:w-auto"> | |
| 40 | − <span class="text-zinc-500 mr-3">~</span> | |
| 41 | − npx create-executor-app | |
| 31 | + {/* HERO & INTERACTIVE BLUEPRINT */} | |
| 32 | + <section class="pt-32 pb-20 px-6 relative z-10"> | |
| 33 | + <div class="max-w-7xl mx-auto flex flex-col lg:flex-row items-center gap-12"> | |
| 34 | + | |
| 35 | + <div class="w-full lg:w-5/12"> | |
| 36 | + <div class="inline-flex border border-blue-200 bg-blue-50 text-blue-700 px-3 py-1 rounded-md text-xs font-bold uppercase tracking-wider mb-6"> | |
| 37 | + System Architecture | |
| 38 | + </div> | |
| 39 | + <h1 class="text-5xl sm:text-6xl font-bold tracking-tight mb-6 text-slate-900"> | |
| 40 | + Wire it once.<br/> | |
| 41 | + Route it everywhere. | |
| 42 | + </h1> | |
| 43 | + <p class="text-lg text-slate-600 leading-relaxed mb-8"> | |
| 44 | + Click the building blocks on the blueprint to see how Executor centralizes API routing, handles context windows, and securely passes data to your agents. | |
| 45 | + </p> | |
| 46 | + <div class="flex flex-col sm:flex-row gap-4"> | |
| 47 | + <a href="/docs" class="bg-slate-900 text-white px-6 py-3 rounded-lg font-semibold shadow-md hover:bg-slate-800 transition-colors text-center">Start Wiring</a> | |
| 48 | + <div class="px-6 py-3 rounded-lg bg-white border border-slate-200 text-slate-600 font-mono text-sm shadow-sm flex items-center gap-3 justify-center"> | |
| 49 | + <span class="text-blue-500 font-bold">$</span> | |
| 50 | + npx create-executor-app | |
| 51 | + </div> | |
| 42 | 52 | </div> |
| 43 | 53 | </div> |
| 44 | − </div> | |
| 45 | 54 | |
| 46 | − {/* Hero Visual: 3-Column Diagram */} | |
| 47 | − <div class="max-w-6xl mx-auto mt-24 relative"> | |
| 48 | − <div class="absolute inset-0 bg-gradient-to-t from-zinc-950 via-transparent to-transparent z-10 h-full w-full pointer-events-none"></div> | |
| 49 | − <div class="grid grid-cols-1 md:grid-cols-3 gap-6 relative z-0"> | |
| 55 | + {/* INTERACTIVE BLUEPRINT SVG DIAGRAM */} | |
| 56 | + <div class="w-full lg:w-7/12 bg-slate-50 border-2 border-slate-200 rounded-2xl shadow-xl p-8 relative"> | |
| 57 | + <div class="absolute top-4 left-4 text-xs font-mono text-slate-400 font-bold uppercase tracking-widest">FIG 1. Routing Topology</div> | |
| 50 | 58 | |
| 51 | − {/* Left: Sources */} | |
| 52 | − <div class="bg-zinc-900/50 border border-zinc-800 rounded-xl p-6 flex flex-col gap-4"> | |
| 53 | − <div class="text-xs font-mono text-zinc-500 uppercase tracking-widest mb-2">Sources In</div> | |
| 54 | − <div class="bg-zinc-950 border border-zinc-800 rounded-lg p-3 flex items-center gap-3"> | |
| 55 | − <div class="w-6 h-6 rounded-full bg-blue-500/20 flex items-center justify-center text-blue-400 text-xs">S</div> | |
| 56 | − <span class="text-sm font-medium">Sentry (OpenAPI)</span> | |
| 57 | − </div> | |
| 58 | − <div class="bg-zinc-950 border border-zinc-800 rounded-lg p-3 flex items-center gap-3"> | |
| 59 | − <div class="w-6 h-6 rounded-full bg-zinc-700/20 flex items-center justify-center text-zinc-300 text-xs">G</div> | |
| 60 | − <span class="text-sm font-medium">GitHub (GraphQL)</span> | |
| 61 | − </div> | |
| 62 | − <div class="bg-zinc-950 border border-zinc-800 rounded-lg p-3 flex items-center gap-3"> | |
| 63 | − <div class="w-6 h-6 rounded-full bg-indigo-500/20 flex items-center justify-center text-indigo-400 text-xs">L</div> | |
| 64 | − <span class="text-sm font-medium">Linear (MCP)</span> | |
| 65 | − </div> | |
| 66 | − </div> | |
| 59 | + <div class="relative w-full aspect-[4/3] mt-8" id="blueprint-container"> | |
| 60 | + {/* SVG Connections */} | |
| 61 | + <svg class="absolute inset-0 w-full h-full pointer-events-none z-0"> | |
| 62 | + {/* Dashed background lines */} | |
| 63 | + <path d="M 15% 20% L 50% 50%" fill="none" stroke="#cbd5e1" stroke-width="2" stroke-dasharray="4 4" /> | |
| 64 | + <path d="M 15% 50% L 50% 50%" fill="none" stroke="#cbd5e1" stroke-width="2" stroke-dasharray="4 4" /> | |
| 65 | + <path d="M 15% 80% L 50% 50%" fill="none" stroke="#cbd5e1" stroke-width="2" stroke-dasharray="4 4" /> | |
| 66 | + <path d="M 50% 50% L 85% 35%" fill="none" stroke="#cbd5e1" stroke-width="2" stroke-dasharray="4 4" /> | |
| 67 | + <path d="M 50% 50% L 85% 65%" fill="none" stroke="#cbd5e1" stroke-width="2" stroke-dasharray="4 4" /> | |
| 68 | + | |
| 69 | + {/* Solid active line (drawn by JS) */} | |
| 70 | + <path d="" fill="none" stroke="#2563eb" stroke-width="3" id="active-line" class="transition-all duration-300" /> | |
| 71 | + </svg> | |
| 67 | 72 | |
| 68 | − {/* Middle: Executor */} | |
| 69 | − <div class="bg-zinc-900 border border-zinc-700 rounded-xl p-6 flex flex-col items-center justify-center text-center relative shadow-2xl shadow-zinc-900"> | |
| 70 | − <div class="absolute -left-3 top-1/2 -translate-y-1/2 w-6 h-[1px] bg-zinc-700 hidden md:block"></div> | |
| 71 | − <div class="absolute -right-3 top-1/2 -translate-y-1/2 w-6 h-[1px] bg-zinc-700 hidden md:block"></div> | |
| 72 | − | |
| 73 | − <div class="w-16 h-16 rounded-xl bg-white shadow-lg flex items-center justify-center mb-6"> | |
| 74 | − <div class="w-8 h-8 rounded bg-black"></div> | |
| 73 | + {/* Nodes */} | |
| 74 | + <button class="bp-node absolute top-[20%] left-[15%] -translate-x-1/2 -translate-y-1/2 w-24 h-16 bg-white border-2 border-slate-300 rounded-lg shadow-sm flex flex-col items-center justify-center cursor-pointer hover:border-blue-500 hover:shadow-md transition-all z-10 group" data-type="source" data-id="1"> | |
| 75 | + <span class="font-bold text-sm text-slate-800 group-hover:text-blue-600">Sentry</span> | |
| 76 | + <span class="text-[10px] text-slate-500 font-mono">OpenAPI</span> | |
| 77 | + </button> | |
| 78 | + <button class="bp-node absolute top-[50%] left-[15%] -translate-x-1/2 -translate-y-1/2 w-24 h-16 bg-white border-2 border-slate-300 rounded-lg shadow-sm flex flex-col items-center justify-center cursor-pointer hover:border-blue-500 hover:shadow-md transition-all z-10 group" data-type="source" data-id="2"> | |
| 79 | + <span class="font-bold text-sm text-slate-800 group-hover:text-blue-600">GitHub</span> | |
| 80 | + <span class="text-[10px] text-slate-500 font-mono">GraphQL</span> | |
| 81 | + </button> | |
| 82 | + <button class="bp-node absolute top-[80%] left-[15%] -translate-x-1/2 -translate-y-1/2 w-24 h-16 bg-white border-2 border-slate-300 rounded-lg shadow-sm flex flex-col items-center justify-center cursor-pointer hover:border-blue-500 hover:shadow-md transition-all z-10 group" data-type="source" data-id="3"> | |
| 83 | + <span class="font-bold text-sm text-slate-800 group-hover:text-blue-600">Linear</span> | |
| 84 | + <span class="text-[10px] text-slate-500 font-mono">MCP</span> | |
| 85 | + </button> | |
| 86 | + | |
| 87 | + {/* Central Hub */} | |
| 88 | + <div class="absolute top-[50%] left-[50%] -translate-x-1/2 -translate-y-1/2 w-32 h-32 bg-blue-600 rounded-2xl shadow-xl shadow-blue-600/30 flex flex-col items-center justify-center z-20 text-white transition-transform duration-300" id="bp-hub"> | |
| 89 | + <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="mb-2"><path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/></svg> | |
| 90 | + <span class="font-bold">Executor Hub</span> | |
| 75 | 91 | </div> |
| 76 | − <h3 class="font-bold text-xl text-white mb-2">Executor Hub</h3> | |
| 77 | − <p class="text-sm text-zinc-400">Unified Catalog &<br/>Auth Proxy</p> | |
| 78 | − </div> | |
| 79 | 92 | |
| 80 | − {/* Right: Agents */} | |
| 81 | − <div class="bg-zinc-900/50 border border-zinc-800 rounded-xl p-6 flex flex-col gap-4"> | |
| 82 | − <div class="text-xs font-mono text-zinc-500 uppercase tracking-widest mb-2">Agents Out</div> | |
| 83 | − <div class="bg-zinc-950 border border-zinc-800 rounded-lg p-3 flex items-center gap-3"> | |
| 84 | − <div class="w-6 h-6 rounded-md bg-orange-500/20 flex items-center justify-center text-orange-400 text-xs">C</div> | |
| 85 | − <span class="text-sm font-medium">Claude Desktop</span> | |
| 93 | + {/* Agents */} | |
| 94 | + <div class="absolute top-[35%] left-[85%] -translate-x-1/2 -translate-y-1/2 w-24 h-16 bg-white border-2 border-slate-300 rounded-lg shadow-sm flex flex-col items-center justify-center z-10 opacity-50 transition-opacity" id="bp-agent-1"> | |
| 95 | + <span class="font-bold text-sm text-slate-800">Claude</span> | |
| 96 | + <span class="text-[10px] text-slate-500 font-mono">Desktop</span> | |
| 86 | 97 | </div> |
| 87 | − <div class="bg-zinc-950 border border-zinc-800 rounded-lg p-3 flex items-center gap-3"> | |
| 88 | − <div class="w-6 h-6 rounded-md bg-zinc-100 flex items-center justify-center text-black text-xs font-serif">C</div> | |
| 89 | − <span class="text-sm font-medium">Cursor</span> | |
| 98 | + <div class="absolute top-[65%] left-[85%] -translate-x-1/2 -translate-y-1/2 w-24 h-16 bg-white border-2 border-slate-300 rounded-lg shadow-sm flex flex-col items-center justify-center z-10 opacity-50 transition-opacity" id="bp-agent-2"> | |
| 99 | + <span class="font-bold text-sm text-slate-800">Cursor</span> | |
| 100 | + <span class="text-[10px] text-slate-500 font-mono">IDE</span> | |
| 90 | 101 | </div> |
| 91 | − <div class="bg-zinc-950 border border-zinc-800 rounded-lg p-3 flex items-center gap-3"> | |
| 92 | − <div class="w-6 h-6 rounded-md bg-green-500/20 flex items-center justify-center text-green-400 text-xs font-mono">{`>_`}</div> | |
| 93 | − <span class="text-sm font-medium">Custom CI Scripts</span> | |
| 102 | + | |
| 103 | + {/* Information Popover */} | |
| 104 | + <div class="absolute bottom-4 right-4 left-4 bg-white/90 backdrop-blur border border-slate-200 p-4 rounded-xl shadow-lg opacity-100 transition-opacity duration-300 z-30 font-mono text-sm" id="bp-info"> | |
| 105 | + Select a source node to simulate routing. | |
| 94 | 106 | </div> |
| 95 | 107 | </div> |
| 96 | − | |
| 97 | 108 | </div> |
| 98 | − </div> | |
| 99 | − </section> | |
| 100 | − | |
| 101 | − {/* Divider */} | |
| 102 | − <div class="max-w-6xl mx-auto px-6"><div class="h-px bg-zinc-900 w-full"></div></div> | |
| 103 | 109 | |
| 104 | − {/* 2. THE CORE PAIN POINT */} | |
| 105 | − <section class="py-32 px-6"> | |
| 106 | − <div class="max-w-4xl mx-auto text-center"> | |
| 107 | − <h2 class="text-3xl md:text-5xl font-bold tracking-tight mb-8 font-serif">End the integration Groundhog Day.</h2> | |
| 108 | − <p class="text-xl text-zinc-400 leading-relaxed font-sans"> | |
| 109 | − Right now, every time a developer wants their agent to talk to Jira or AWS, they have to configure it locally. When you switch to a new agent, you have to do it all over again. Executor centralizes your tools. You expose your APIs and specs in one place, and the capabilities are instantly synced and shared across every agent your team uses. | |
| 110 | − </p> | |
| 111 | 110 | </div> |
| 112 | 111 | </section> |
| 113 | 112 | |
| 114 | − {/* 3. CONTEXT & SCALE */} | |
| 115 | − <section class="py-32 px-6 bg-zinc-900/20 border-y border-zinc-900"> | |
| 116 | − <div class="max-w-6xl mx-auto grid grid-cols-1 md:grid-cols-2 gap-16 items-center"> | |
| 113 | + {/* CONTEXT BLOAT & CODE */} | |
| 114 | + <section class="py-24 px-6 relative z-10"> | |
| 115 | + <div class="max-w-6xl mx-auto grid grid-cols-1 lg:grid-cols-2 gap-16 items-center"> | |
| 117 | 116 | <div> |
| 118 | − <h2 class="text-3xl md:text-4xl font-bold tracking-tight mb-6 font-serif">Infinite capabilities.<br/>Zero context bloat.</h2> | |
| 119 | − <p class="text-lg text-zinc-400 leading-relaxed"> | |
| 120 | − Feeding thousands of tool descriptions into an agent destroys its context window and ruins reasoning. Executor solves this. No matter how massive your tool catalog gets, Executor intelligently routes and exposes only what the agent needs, when it needs it. You get the power of 10,000 tools without degrading your agent's performance. | |
| 117 | + <h2 class="text-4xl font-bold tracking-tight mb-6 text-slate-900"> | |
| 118 | + Infinite catalog.<br/>Zero context bloat. | |
| 119 | + </h2> | |
| 120 | + <p class="text-lg text-slate-600 leading-relaxed mb-8"> | |
| 121 | + Feeding thousands of tool descriptions into an agent destroys its context window and reasoning. Executor solves this elegantly. No matter how massive your tool catalog gets, Executor selectively routes and exposes only what the agent needs. | |
| 121 | 122 | </p> |
| 122 | 123 | </div> |
| 123 | − <div class="bg-zinc-950 border border-zinc-800 rounded-xl p-6 font-mono text-sm text-zinc-300 shadow-xl overflow-hidden relative"> | |
| 124 | − <div class="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-blue-500 to-indigo-500"></div> | |
| 125 | − <div class="text-zinc-500 mb-4">// Executor exposes one tool: execute</div> | |
| 126 | − <div class="text-purple-400">await</div> <div class="inline">executor.search(</div><div class="text-green-400 inline">'*aws*rds*'</div><div class="inline">)</div> | |
| 127 | − <br/><br/> | |
| 128 | − <div class="text-zinc-500 mb-2">// Agent runs code in a sandbox</div> | |
| 129 | − <div class="text-purple-400">const</div> <div class="inline">db = tools.aws.rds.describeDBInstances()</div> | |
| 130 | − <br/> | |
| 131 | − <div class="text-purple-400">if</div> <div class="inline">(db.status ===</div> <div class="text-green-400 inline">'stopped'</div><div class="inline">) {'{'}</div> | |
| 132 | − <br/> | |
| 133 | − <div class="text-purple-400">await</div> <div class="inline">tools.slack.notify({'...'})</div> | |
| 134 | − <br/> | |
| 135 | − <div class="inline">{'}'}</div> | |
| 136 | − </div> | |
| 137 | − </div> | |
| 138 | − </section> | |
| 139 | − | |
| 140 | − {/* 4. INTERACTIVE POLICIES */} | |
| 141 | − <section class="py-32 px-6 overflow-hidden"> | |
| 142 | − <div class="max-w-6xl mx-auto"> | |
| 143 | − <div class="text-center max-w-3xl mx-auto mb-16"> | |
| 144 | − <h2 class="text-3xl md:text-5xl font-bold tracking-tight mb-6 font-serif">Trust your agents to work.<br/>Never trust them with the keys.</h2> | |
| 145 | − <p class="text-lg text-zinc-400 leading-relaxed"> | |
| 146 | − Give your agents access to production, safely. Executor’s policy engine lets you define exactly what happens when an agent tries to take action. Auto-approve safe queries, strictly block destructive actions, or require human-in-the-loop approval before an agent drops a database or refunds a charge. | |
| 147 | − </p> | |
| 148 | − </div> | |
| 149 | − | |
| 150 | − {/* Interactive Demo UI */} | |
| 151 | − <div class="max-w-4xl mx-auto bg-zinc-900 border border-zinc-800 rounded-2xl shadow-2xl overflow-hidden" id="policy-demo"> | |
| 152 | − <div class="border-b border-zinc-800 p-4 flex items-center justify-between bg-zinc-950"> | |
| 153 | − <div class="flex gap-2"> | |
| 154 | − <div class="w-3 h-3 rounded-full bg-zinc-800"></div> | |
| 155 | − <div class="w-3 h-3 rounded-full bg-zinc-800"></div> | |
| 156 | − <div class="w-3 h-3 rounded-full bg-zinc-800"></div> | |
| 157 | − </div> | |
| 158 | − <div class="text-xs font-mono text-zinc-500">executor-policy-engine</div> | |
| 159 | − <div></div> | |
| 124 | + | |
| 125 | + {/* IDE Mockup */} | |
| 126 | + <div class="bg-slate-900 rounded-2xl shadow-xl overflow-hidden border border-slate-800"> | |
| 127 | + <div class="flex items-center gap-2 px-4 py-3 bg-slate-950 border-b border-slate-800"> | |
| 128 | + <div class="w-3 h-3 rounded-full bg-slate-700"></div> | |
| 129 | + <div class="w-3 h-3 rounded-full bg-slate-700"></div> | |
| 130 | + <div class="w-3 h-3 rounded-full bg-slate-700"></div> | |
| 131 | + <span class="ml-4 text-xs font-mono text-slate-500">sandbox.ts</span> | |
| 160 | 132 | </div> |
| 161 | − | |
| 162 | − <div class="grid grid-cols-1 md:grid-cols-3"> | |
| 163 | − {/* Sidebar Controls */} | |
| 164 | − <div class="col-span-1 border-r border-zinc-800 bg-zinc-950/50 p-6 flex flex-col gap-4"> | |
| 165 | − <div class="text-xs font-bold tracking-wider text-zinc-500 uppercase mb-2">Select Policy</div> | |
| 166 | − | |
| 167 | − <button class="policy-btn active flex flex-col items-start p-3 rounded-lg border border-zinc-700 bg-zinc-800 text-left transition-all" data-policy="approve"> | |
| 168 | − <span class="text-sm font-bold text-green-400 mb-1 flex items-center gap-2"> | |
| 169 | − <span class="w-2 h-2 rounded-full bg-green-400"></span> Auto-Approve | |
| 170 | − </span> | |
| 171 | − <span class="text-xs text-zinc-400">Safe read-only actions.</span> | |
| 172 | − </button> | |
| 173 | − | |
| 174 | − <button class="policy-btn flex flex-col items-start p-3 rounded-lg border border-zinc-800 hover:border-zinc-700 text-left transition-all" data-policy="block"> | |
| 175 | − <span class="text-sm font-bold text-red-400 mb-1 flex items-center gap-2"> | |
| 176 | − <span class="w-2 h-2 rounded-full bg-red-400"></span> Block | |
| 177 | − </span> | |
| 178 | − <span class="text-xs text-zinc-400">Highly destructive actions.</span> | |
| 179 | − </button> | |
| 180 | − | |
| 181 | − <button class="policy-btn flex flex-col items-start p-3 rounded-lg border border-zinc-800 hover:border-zinc-700 text-left transition-all" data-policy="human"> | |
| 182 | − <span class="text-sm font-bold text-yellow-400 mb-1 flex items-center gap-2"> | |
| 183 | − <span class="w-2 h-2 rounded-full bg-yellow-400"></span> Require Approval | |
| 184 | − </span> | |
| 185 | − <span class="text-xs text-zinc-400">Pause and ask a human.</span> | |
| 186 | − </button> | |
| 133 | + <div class="p-6 font-mono text-[13px] leading-loose text-slate-300"> | |
| 134 | + <div class="text-slate-500 mb-2">// Agents execute dynamic discovery in a secure V8 isolate</div> | |
| 135 | + <div> | |
| 136 | + <span class="text-pink-400">const</span> <span class="text-blue-300">tools</span> <span class="text-pink-400">=</span> <span class="text-purple-400">await</span> <span class="text-white">executor.search</span>(<span class="text-emerald-400">'*aws*rds*'</span>) | |
| 187 | 137 | </div> |
| 188 | − | |
| 189 | − {/* Execution Viewer */} | |
| 190 | − <div class="col-span-2 p-6 bg-zinc-900 flex flex-col justify-center min-h-[300px] relative font-mono text-sm"> | |
| 191 | − {/* Output: Approve */} | |
| 192 | − <div id="output-approve" class="policy-output space-y-4"> | |
| 193 | − <div class="flex gap-3 text-zinc-400"> | |
| 194 | − <span class="text-blue-400">Agent</span> | |
| 195 | − <span>Executing: <span class="text-white">sentry.list_issues()</span></span> | |
| 196 | − </div> | |
| 197 | − <div class="flex gap-3 text-zinc-400"> | |
| 198 | − <span class="text-green-400">Policy</span> | |
| 199 | − <span>Matched rule: <span class="text-white">"sentry.*"</span> -> Allow</span> | |
| 200 | − </div> | |
| 201 | − <div class="flex gap-3 text-zinc-400"> | |
| 202 | − <span class="text-zinc-500">System</span> | |
| 203 | − <span class="text-white bg-zinc-800 px-2 py-1 rounded">✔ Success: Returned 12 issues.</span> | |
| 204 | − </div> | |
| 205 | − </div> | |
| 206 | − | |
| 207 | − {/* Output: Block */} | |
| 208 | − <div id="output-block" class="policy-output space-y-4 hidden"> | |
| 209 | − <div class="flex gap-3 text-zinc-400"> | |
| 210 | − <span class="text-blue-400">Agent</span> | |
| 211 | − <span>Executing: <span class="text-white">aws.ec2.terminate_instances()</span></span> | |
| 212 | − </div> | |
| 213 | − <div class="flex gap-3 text-zinc-400"> | |
| 214 | − <span class="text-red-400">Policy</span> | |
| 215 | − <span>Matched rule: <span class="text-white">"aws.ec2.terminate*"</span> -> Block</span> | |
| 216 | − </div> | |
| 217 | − <div class="flex gap-3 text-zinc-400"> | |
| 218 | − <span class="text-zinc-500">System</span> | |
| 219 | − <span class="text-red-400 bg-red-400/10 px-2 py-1 rounded border border-red-400/20">✖ Error: Action explicitly forbidden by organization policy.</span> | |
| 220 | − </div> | |
| 221 | − </div> | |
| 222 | − | |
| 223 | − {/* Output: Human */} | |
| 224 | − <div id="output-human" class="policy-output space-y-4 hidden"> | |
| 225 | − <div class="flex gap-3 text-zinc-400"> | |
| 226 | − <span class="text-blue-400">Agent</span> | |
| 227 | − <span>Executing: <span class="text-white">github.repos.delete()</span></span> | |
| 228 | − </div> | |
| 229 | − <div class="flex gap-3 text-zinc-400"> | |
| 230 | − <span class="text-yellow-400">Policy</span> | |
| 231 | − <span>Matched rule: <span class="text-white">"github.*.delete"</span> -> Require Approval</span> | |
| 232 | − </div> | |
| 233 | − <div class="flex gap-3 text-zinc-400 animate-pulse"> | |
| 234 | − <span class="text-zinc-500">System</span> | |
| 235 | − <span class="text-yellow-400">⏸️ Execution paused. Waiting for human approval...</span> | |
| 236 | − </div> | |
| 237 | − <div class="mt-4 border border-zinc-700 bg-zinc-950 p-4 rounded-lg shadow-xl shadow-black/50 ml-12 animate-fade-in relative"> | |
| 238 | − <div class="text-xs text-zinc-500 mb-2">Incoming Approval Request</div> | |
| 239 | − <div class="text-sm text-white mb-4">Agent wants to delete repository: `legacy-api`.</div> | |
| 240 | − <div class="flex gap-3"> | |
| 241 | − <button class="px-3 py-1.5 bg-green-500/20 text-green-400 border border-green-500/30 rounded text-xs hover:bg-green-500/30">Approve</button> | |
| 242 | − <button class="px-3 py-1.5 bg-red-500/20 text-red-400 border border-red-500/30 rounded text-xs hover:bg-red-500/30">Deny</button> | |
| 243 | − </div> | |
| 244 | − </div> | |
| 245 | − </div> | |
| 138 | + <br/> | |
| 139 | + <div> | |
| 140 | + <span class="text-pink-400">const</span> <span class="text-blue-300">db</span> <span class="text-pink-400">=</span> <span class="text-white">tools.aws.rds.describeDBInstances</span>() | |
| 141 | + </div> | |
| 142 | + <div> | |
| 143 | + <span class="text-purple-400">if</span> (<span class="text-blue-300">db.status</span> <span class="text-pink-400">===</span> <span class="text-emerald-400">'stopped'</span>) {'{'} | |
| 144 | + </div> | |
| 145 | + <div class="pl-6"> | |
| 146 | + <span class="text-purple-400">await</span> <span class="text-white">tools.slack.notify</span>({'{'} <span class="text-blue-300">message:</span> <span class="text-emerald-400">'DB down'</span> {'}'}) | |
| 246 | 147 | </div> |
| 148 | + <div>{'}'}</div> | |
| 247 | 149 | </div> |
| 248 | 150 | </div> |
| 249 | 151 | </div> |
| 250 | 152 | </section> |
| 251 | 153 | |
| 252 | − {/* 5. FLEXIBLE AUTH */} | |
| 253 | − <section class="py-32 px-6 bg-zinc-900/20 border-y border-zinc-900"> | |
| 254 | − <div class="max-w-6xl mx-auto grid grid-cols-1 md:grid-cols-2 gap-16 items-center"> | |
| 255 | − <div class="order-2 md:order-1 flex flex-col gap-4"> | |
| 256 | − <div class="bg-zinc-950 border border-zinc-800 rounded-xl p-5 flex items-center justify-between"> | |
| 257 | − <div> | |
| 258 | − <div class="font-medium text-white mb-1">Slack Bot Token</div> | |
| 259 | − <div class="text-xs text-zinc-400">Used for read/write to #engineering</div> | |
| 260 | − </div> | |
| 261 | − <div class="text-xs font-mono bg-blue-500/10 text-blue-400 px-2 py-1 rounded border border-blue-500/20">Org-Level</div> | |
| 154 | + {/* AUTH ARCHITECTURE */} | |
| 155 | + <section class="py-24 px-6 border-t border-slate-200 relative z-10 bg-slate-50"> | |
| 156 | + <div class="max-w-6xl mx-auto text-center"> | |
| 157 | + <h2 class="text-4xl font-bold text-slate-900 mb-6">Centralized auth. Zero leaked secrets.</h2> | |
| 158 | + <p class="text-lg text-slate-600 leading-relaxed max-w-2xl mx-auto mb-16"> | |
| 159 | + Stop pasting API keys into agent prompts or local env files. Executor acts as a secure proxy. Set global Org-level tokens for shared services, or enforce Per-User OAuth so agents only act with your exact permissions. | |
| 160 | + </p> | |
| 161 | + | |
| 162 | + {/* Interactive Exploded View */} | |
| 163 | + <div class="relative h-[400px] flex flex-col items-center justify-center group cursor-crosshair"> | |
| 164 | + {/* Layer 1: App */} | |
| 165 | + <div class="absolute top-[20%] w-[400px] h-[100px] bg-white border-2 border-slate-300 rounded-xl shadow-md flex items-center justify-center font-bold text-slate-600 transition-all duration-500 group-hover:-translate-y-12 group-hover:scale-105 z-30"> | |
| 166 | + Agent Interface (Claude / Cursor) | |
| 262 | 167 | </div> |
| 263 | − <div class="bg-zinc-950 border border-zinc-800 rounded-xl p-5 flex items-center justify-between"> | |
| 264 | − <div> | |
| 265 | − <div class="font-medium text-white mb-1">GitHub Personal Access Token</div> | |
| 266 | − <div class="text-xs text-zinc-400">Authenticates as the active user</div> | |
| 267 | − </div> | |
| 268 | − <div class="text-xs font-mono bg-purple-500/10 text-purple-400 px-2 py-1 rounded border border-purple-500/20">Per-User OAuth</div> | |
| 168 | + {/* Layer 2: Auth Proxy */} | |
| 169 | + <div class="absolute top-[40%] w-[420px] h-[100px] bg-blue-600 border-2 border-blue-700 rounded-xl shadow-xl shadow-blue-600/20 flex items-center justify-between px-8 font-bold text-white transition-all duration-500 group-hover:scale-105 z-20"> | |
| 170 | + <span>Executor Auth Proxy</span> | |
| 171 | + <span class="text-xs bg-white/20 text-white px-2 py-1 rounded-md backdrop-blur-sm border border-white/20">Token Injector</span> | |
| 269 | 172 | </div> |
| 270 | − </div> | |
| 271 | − <div class="order-1 md:order-2"> | |
| 272 | − <h2 class="text-3xl md:text-4xl font-bold tracking-tight mb-6 font-serif">Centralized auth.<br/>Zero leaked secrets.</h2> | |
| 273 | − <p class="text-lg text-zinc-400 leading-relaxed"> | |
| 274 | − Stop pasting API keys into agent prompts or local env files. Executor acts as a secure authentication proxy. Set global Org-level tokens for shared services, or enforce Per-User OAuth so agents only act with the exact permissions of the human commanding them. The agent never sees the raw keys. | |
| 173 | + {/* Layer 3: API */} | |
| 174 | + <div class="absolute top-[60%] w-[440px] h-[100px] bg-slate-100 border-2 border-slate-400 rounded-xl shadow-inner flex flex-col items-center justify-center font-bold text-slate-700 transition-all duration-500 group-hover:translate-y-12 group-hover:scale-105 z-10"> | |
| 175 | + <span>Internal APIs / External Services</span> | |
| 176 | + <span class="text-xs font-normal text-slate-500 mt-1">Authenticated Requests Only</span> | |
| 177 | + </div> | |
| 178 | + <p class="absolute bottom-0 text-slate-500 text-sm font-medium opacity-0 group-hover:opacity-100 transition-opacity duration-500"> | |
| 179 | + Hover to expand. Tokens never reach the agent—they are securely injected mid-flight. | |
| 275 | 180 | </p> |
| 276 | 181 | </div> |
| 277 | 182 | </div> |
| 278 | 183 | </section> |
| 279 | 184 | |
| 280 | − {/* 6. UNIVERSAL COMPATIBILITY */} | |
| 281 | − <section class="py-32 px-6"> | |
| 282 | − <div class="max-w-4xl mx-auto text-center"> | |
| 283 | − <h2 class="text-3xl md:text-5xl font-bold tracking-tight mb-8 font-serif">Bring your own agent.</h2> | |
| 284 | − <p class="text-xl text-zinc-400 leading-relaxed font-sans mb-12"> | |
| 285 | − Executor speaks the Model Context Protocol (MCP) natively. Whether your team prefers chatting in Claude, coding in Cursor, or building custom agents, connecting them to Executor takes one click. Swap agents whenever you want; your tool catalog stays exactly where it is. | |
| 286 | − </p> | |
| 287 | − <div class="flex flex-wrap items-center justify-center gap-4 text-sm font-medium text-zinc-400"> | |
| 288 | − <div class="px-4 py-2 border border-zinc-800 rounded-full bg-zinc-900">Cursor</div> | |
| 289 | − <div class="px-4 py-2 border border-zinc-800 rounded-full bg-zinc-900">Claude Desktop</div> | |
| 290 | − <div class="px-4 py-2 border border-zinc-800 rounded-full bg-zinc-900">ChatGPT</div> | |
| 291 | − <div class="px-4 py-2 border border-zinc-800 rounded-full bg-zinc-900">Windsurf</div> | |
| 292 | − <div class="px-4 py-2 border border-zinc-800 rounded-full bg-zinc-900">Custom MCP Clients</div> | |
| 185 | + {/* POLICY ENGINE / SAFETY */} | |
| 186 | + <section class="py-24 px-6 border-t border-slate-200 relative z-10 bg-white"> | |
| 187 | + <div class="max-w-6xl mx-auto flex flex-col lg:flex-row gap-16 items-center"> | |
| 188 | + <div class="lg:w-1/2"> | |
| 189 | + <div class="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-emerald-100 text-emerald-700 font-semibold text-xs mb-6 border border-emerald-200"> | |
| 190 | + <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path></svg> | |
| 191 | + Safety First | |
| 192 | + </div> | |
| 193 | + <h2 class="text-4xl font-bold tracking-tight mb-6 text-slate-900"> | |
| 194 | + Trust the agent.<br/>Verify the action. | |
| 195 | + </h2> | |
| 196 | + <p class="text-lg text-slate-600 leading-relaxed mb-8"> | |
| 197 | + Give your agents access to production, safely. Executor’s policy engine lets you define exactly what happens when an agent tries to take action. | |
| 198 | + </p> | |
| 199 | + <div class="flex flex-col gap-3"> | |
| 200 | + <div class="flex items-center gap-4 bg-slate-50 border border-slate-200 p-4 rounded-xl"> | |
| 201 | + <div class="w-10 h-10 rounded-full bg-emerald-100 border border-emerald-200 flex items-center justify-center text-emerald-600 shrink-0 font-bold">✓</div> | |
| 202 | + <div><div class="font-bold text-slate-900">Auto-Approve</div><div class="text-sm text-slate-500">For safe read-only queries</div></div> | |
| 203 | + </div> | |
| 204 | + <div class="flex items-center gap-4 bg-slate-50 border border-slate-200 p-4 rounded-xl"> | |
| 205 | + <div class="w-10 h-10 rounded-full bg-rose-100 border border-rose-200 flex items-center justify-center text-rose-600 shrink-0 font-bold">✕</div> | |
| 206 | + <div><div class="font-bold text-slate-900">Hard Block</div><div class="text-sm text-slate-500">For dangerous destructive actions</div></div> | |
| 207 | + </div> | |
| 208 | + <div class="flex items-center gap-4 bg-slate-50 border border-slate-200 p-4 rounded-xl"> | |
| 209 | + <div class="w-10 h-10 rounded-full bg-amber-100 border border-amber-200 flex items-center justify-center text-amber-600 shrink-0 font-bold">!</div> | |
| 210 | + <div><div class="font-bold text-slate-900">Require Human</div><div class="text-sm text-slate-500">Pause execution and ask for permission via Slack or UI</div></div> | |
| 211 | + </div> | |
| 212 | + </div> | |
| 213 | + </div> | |
| 214 | + | |
| 215 | + <div class="lg:w-1/2 w-full relative"> | |
| 216 | + <div class="bg-slate-900 rounded-2xl p-6 shadow-xl border border-slate-800 font-mono text-sm overflow-hidden text-slate-300"> | |
| 217 | + <div class="flex gap-2 mb-6 border-b border-slate-800 pb-4"> | |
| 218 | + <div class="text-xs font-bold text-slate-500 uppercase tracking-widest">Execution Log</div> | |
| 219 | + </div> | |
| 220 | + <div class="mb-4"> | |
| 221 | + <span class="text-blue-400">Agent</span> requests <span class="text-white">github.repos.delete()</span> | |
| 222 | + </div> | |
| 223 | + <div class="mb-4"> | |
| 224 | + <span class="text-emerald-400">System</span> Evaluating policy... <span class="text-amber-400">Match: "github.*.delete" -> Elicit</span> | |
| 225 | + </div> | |
| 226 | + <div class="mb-6 animate-pulse text-amber-400"> | |
| 227 | + ⏸️ Execution paused. Awaiting human... | |
| 228 | + </div> | |
| 229 | + <div class="bg-white text-slate-900 p-5 rounded-xl shadow-2xl relative font-sans ml-4 border border-slate-200"> | |
| 230 | + <div class="absolute top-0 left-0 w-1 h-full bg-amber-400 rounded-l-xl"></div> | |
| 231 | + <div class="font-bold text-base mb-1">Approval Request</div> | |
| 232 | + <div class="text-slate-600 text-sm mb-4">Agent wants to delete <code class="bg-slate-100 px-1 rounded border border-slate-200 text-rose-600">legacy-api</code></div> | |
| 233 | + <div class="flex gap-2"> | |
| 234 | + <button class="bg-blue-600 text-white px-4 py-2 rounded-lg text-sm font-bold hover:bg-blue-700 transition-colors shadow-sm">Authorize</button> | |
| 235 | + <button class="bg-slate-50 border border-slate-200 text-slate-600 px-4 py-2 rounded-lg text-sm font-bold hover:bg-slate-100 transition-colors shadow-sm">Reject</button> | |
| 236 | + </div> | |
| 237 | + </div> | |
| 238 | + </div> | |
| 293 | 239 | </div> |
| 294 | 240 | </div> |
| 295 | 241 | </section> |
| 296 | 242 | |
| 297 | − {/* 7. BOTTOM CTA */} | |
| 298 | − <section class="py-32 px-6 bg-white text-black text-center"> | |
| 243 | + {/* BOTTOM CTA */} | |
| 244 | + <section class="py-32 px-6 border-t border-slate-200 text-center bg-slate-50 relative z-10"> | |
| 299 | 245 | <div class="max-w-3xl mx-auto"> |
| 300 | − <h2 class="text-4xl md:text-6xl font-bold tracking-tight mb-8 font-serif">Where your agents go<br/>to get work done.</h2> | |
| 246 | + <h2 class="text-4xl sm:text-5xl font-bold tracking-tight text-slate-900 mb-8"> | |
| 247 | + Ready to supercharge your agents? | |
| 248 | + </h2> | |
| 249 | + <p class="text-xl text-slate-600 mb-12"> | |
| 250 | + Executor is open-source and easy to deploy. Start routing your APIs directly to your team's LLM clients today. | |
| 251 | + </p> | |
| 301 | 252 | <div class="flex flex-col sm:flex-row items-center justify-center gap-4"> |
| 302 | − <a href="/docs" class="bg-black text-white px-8 py-4 rounded-lg text-lg font-semibold hover:bg-zinc-800 transition-colors w-full sm:w-auto"> | |
| 303 | − Get Started | |
| 253 | + <a href="/docs" class="bg-blue-600 text-white px-8 py-4 rounded-xl text-lg font-bold shadow-lg shadow-blue-600/30 hover:bg-blue-700 hover:-translate-y-1 transition-all"> | |
| 254 | + Get Started for Free | |
| 304 | 255 | </a> |
| 305 | − <a href="https://github.com/executor-js/executor" class="bg-zinc-200 text-black px-8 py-4 rounded-lg text-lg font-semibold hover:bg-zinc-300 transition-colors w-full sm:w-auto"> | |
| 306 | − View Documentation | |
| 256 | + <a href="https://github.com/executor-js/executor" class="px-8 py-4 rounded-xl bg-white border border-slate-200 text-slate-700 text-lg font-bold hover:bg-slate-50 transition-colors shadow-sm"> | |
| 257 | + View on GitHub | |
| 307 | 258 | </a> |
| 308 | 259 | </div> |
| 309 | 260 | </div> |
| 310 | 261 | </section> |
| 311 | 262 | |
| 312 | − {/* FOOTER */} | |
| 313 | − <footer class="bg-zinc-950 py-12 px-6 border-t border-zinc-900"> | |
| 314 | − <div class="max-w-6xl mx-auto flex flex-col md:flex-row justify-between items-center gap-4"> | |
| 315 | − <div class="flex items-center gap-2 font-mono font-semibold text-lg tracking-tight text-white"> | |
| 316 | − <div class="w-5 h-5 rounded bg-white"></div> | |
| 317 | − Executor | |
| 318 | − </div> | |
| 319 | − <div class="text-sm text-zinc-500"> | |
| 320 | − © {new Date().getFullYear()} Executor. All rights reserved. | |
| 321 | − </div> | |
| 322 | − </div> | |
| 263 | + <footer class="py-8 px-6 border-t border-slate-200 bg-white text-center text-sm font-medium text-slate-500 relative z-10"> | |
| 264 | + © {new Date().getFullYear()} Executor. All rights reserved. | |
| 323 | 265 | </footer> |
| 324 | 266 | |
| 325 | − </main> | |
| 267 | + <script> | |
| 268 | + document.addEventListener('DOMContentLoaded', () => { | |
| 269 | + const nodes = document.querySelectorAll('.bp-node'); | |
| 270 | + const activeLine = document.getElementById('active-line') as any; | |
| 271 | + const info = document.getElementById('bp-info'); | |
| 272 | + const hub = document.getElementById('bp-hub'); | |
| 273 | + const agent1 = document.getElementById('bp-agent-1'); | |
| 274 | + const agent2 = document.getElementById('bp-agent-2'); | |
| 326 | 275 | |
| 327 | − <style> | |
| 328 | − @keyframes fadeIn { | |
| 329 | − from { opacity: 0; transform: translateY(5px); } | |
| 330 | − to { opacity: 1; transform: translateY(0); } | |
| 331 | − } | |
| 332 | − .animate-fade-in { | |
| 333 | − animation: fadeIn 0.3s ease-out forwards; | |
| 334 | − } | |
| 335 | − </style> | |
| 276 | + nodes.forEach(node => { | |
| 277 | + node.addEventListener('click', () => { | |
| 278 | + const id = node.getAttribute('data-id'); | |
| 279 | + const yPos = id === '1' ? '20%' : id === '2' ? '50%' : '80%'; | |
| 280 | + const sourceName = node.querySelector('span').textContent; | |
| 281 | + | |
| 282 | + // Draw line to hub | |
| 283 | + activeLine.setAttribute('d', `M 15% ${yPos} L 50% 50%`); | |
| 284 | + info.style.opacity = '1'; | |
| 285 | + info.innerHTML = `<span class="text-blue-600">Event:</span> Incoming schema translation from <strong>${sourceName}</strong>...`; | |
| 336 | 286 | |
| 337 | − <script> | |
| 338 | − // Interactive Policy Demo Logic | |
| 339 | − document.addEventListener('DOMContentLoaded', () => { | |
| 340 | − const buttons = document.querySelectorAll('.policy-btn'); | |
| 341 | − const outputs = document.querySelectorAll('.policy-output'); | |
| 287 | + // Hub pulse | |
| 288 | + hub.classList.add('scale-110'); | |
| 289 | + setTimeout(() => hub.classList.remove('scale-110'), 200); | |
| 342 | 290 | |
| 343 | − buttons.forEach(btn => { | |
| 344 | − btn.addEventListener('click', () => { | |
| 345 | − // Remove active state | |
| 346 | − buttons.forEach(b => { | |
| 347 | − b.classList.remove('bg-zinc-800', 'border-zinc-700'); | |
| 348 | − b.classList.add('border-zinc-800'); | |
| 291 | + setTimeout(() => { | |
| 292 | + const agentId = Math.random() > 0.5 ? 1 : 2; | |
| 293 | + const agentY = agentId === 1 ? '35%' : '65%'; | |
| 294 | + const targetAgent = agentId === 1 ? agent1 : agent2; | |
| 295 | + const agentName = targetAgent.querySelector('span').textContent; | |
| 296 | + | |
| 297 | + // Extend line to agent | |
| 298 | + activeLine.setAttribute('d', `M 15% ${yPos} L 50% 50% L 85% ${agentY}`); | |
| 299 | + info.innerHTML = `<span class="text-emerald-600">Success:</span> Payload securely delivered to <strong>${agentName}</strong>.`; | |
| 300 | + | |
| 301 | + targetAgent.classList.remove('opacity-50'); | |
| 302 | + targetAgent.classList.add('border-blue-500', 'ring-4', 'ring-blue-500/20'); | |
| 303 | + | |
| 304 | + setTimeout(() => { | |
| 305 | + activeLine.setAttribute('d', ''); | |
| 306 | + targetAgent.classList.add('opacity-50'); | |
| 307 | + targetAgent.classList.remove('border-blue-500', 'ring-4', 'ring-blue-500/20'); | |
| 308 | + }, 1500); | |
| 309 | + }, 500); | |
| 349 | 310 | }); |
| 350 | − | |
| 351 | − // Add active state to clicked | |
| 352 | − btn.classList.add('bg-zinc-800', 'border-zinc-700'); | |
| 353 | − btn.classList.remove('border-zinc-800'); | |
| 354 | − | |
| 355 | − // Hide all outputs | |
| 356 | − outputs.forEach(out => out.classList.add('hidden')); | |
| 357 | − | |
| 358 | − // Show target output | |
| 359 | − const target = btn.getAttribute('data-policy'); | |
| 360 | − document.getElementById(`output-${target}`).classList.remove('hidden'); | |
| 361 | 311 | }); |
| 362 | 312 | }); |
| 363 | − }); | |
| 364 | − </script> | |
| 313 | + </script> | |
| 314 | + </main> | |
| 365 | 315 | </Layout> |