Commit Β·
34b6cef
0
Parent(s):
Clean fresh deployment
Browse files- .gitattributes +35 -0
- .gitignore +10 -0
- Dockerfile +19 -0
- README.md +12 -0
- frontend/README.md +73 -0
- frontend/app/layout.tsx +27 -0
- frontend/app/page.tsx +182 -0
- frontend/components/agents/AgentCard.tsx +284 -0
- frontend/components/agents/AgentDecisionPanel.tsx +280 -0
- frontend/components/agents/AgentPipeline.tsx +151 -0
- frontend/components/agents/LiveAgentThinking.tsx +185 -0
- frontend/components/animations/ParticleBackground.tsx +13 -0
- frontend/components/animations/ParticleCanvas.tsx +183 -0
- frontend/components/architecture/ArchitectureSummary.tsx +293 -0
- frontend/components/architecture/FinalArchitectureBlueprint.tsx +268 -0
- frontend/components/layout/Header.tsx +131 -0
- frontend/components/providers/AntdProvider.tsx +32 -0
- frontend/components/ui/HeroSection.tsx +369 -0
- frontend/components/ui/Navbar.tsx +140 -0
- frontend/components/workflow/BeforeAfterWorkflow.tsx +284 -0
- frontend/components/workflow/FlowchartNode.tsx +249 -0
- frontend/components/workflow/WorkflowBuilder.tsx +550 -0
- frontend/components/workflow/WorkflowComparison.tsx +286 -0
- frontend/components/workflow/WorkflowNode.tsx +226 -0
- frontend/components/workflow/WorkflowTypes.ts +27 -0
- frontend/legacy/app.py +81 -0
- frontend/lib/api.ts +100 -0
- frontend/lib/exampleWorkflows.ts +482 -0
- frontend/lib/types.ts +47 -0
- frontend/next-env.d.ts +6 -0
- frontend/package-lock.json +0 -0
- frontend/package.json +33 -0
- frontend/styles/globals.css +159 -0
- frontend/tsconfig.json +37 -0
- frontend/tsconfig.tsbuildinfo +0 -0
- requirements.txt +12 -0
- src/agents/architect.py +226 -0
- src/agents/critic.py +171 -0
- src/agents/executive_summary.py +199 -0
- src/agents/refiner.py +275 -0
- src/api/main.py +109 -0
- src/api/pdf_generator.py +444 -0
- src/config/agents.yaml +13 -0
- src/config/tasks.yaml +10 -0
- src/prompts/workflow_prompt.py +158 -0
- src/state/state.py +24 -0
- src/tools/json_parser.py +48 -0
- src/tools/llm.py +54 -0
- src/workflows/crew.py +186 -0
.gitattributes
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
node_modules/
|
| 2 |
+
.next/
|
| 3 |
+
venv/
|
| 4 |
+
__pycache__/
|
| 5 |
+
*.pyc
|
| 6 |
+
.env
|
| 7 |
+
.env.local
|
| 8 |
+
dist/
|
| 9 |
+
build/
|
| 10 |
+
*.log
|
Dockerfile
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM node:20-bullseye
|
| 2 |
+
|
| 3 |
+
RUN apt-get update && apt-get install -y python3 python3-pip python3-venv
|
| 4 |
+
|
| 5 |
+
WORKDIR /app
|
| 6 |
+
|
| 7 |
+
COPY . .
|
| 8 |
+
|
| 9 |
+
RUN pip3 install --no-cache-dir -r requirements.txt
|
| 10 |
+
|
| 11 |
+
WORKDIR /app/frontend
|
| 12 |
+
RUN npm install
|
| 13 |
+
RUN npm run build
|
| 14 |
+
|
| 15 |
+
WORKDIR /app
|
| 16 |
+
|
| 17 |
+
EXPOSE 7860
|
| 18 |
+
|
| 19 |
+
CMD sh -c "python3 -m uvicorn src.api.main:app --host 0.0.0.0 --port 8000 & cd frontend && npm run start -- --port 7860"
|
README.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Systemforge Ai
|
| 3 |
+
emoji: π₯
|
| 4 |
+
colorFrom: pink
|
| 5 |
+
colorTo: gray
|
| 6 |
+
sdk: docker
|
| 7 |
+
pinned: false
|
| 8 |
+
license: mit
|
| 9 |
+
short_description: Multi-agent AI platform that transforms enterprise workflows
|
| 10 |
+
---
|
| 11 |
+
|
| 12 |
+
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
frontend/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SystemForge AI β Frontend
|
| 2 |
+
|
| 3 |
+
Premium Next.js frontend for the SystemForge AI multi-agent architecture engine.
|
| 4 |
+
|
| 5 |
+
## Tech Stack
|
| 6 |
+
|
| 7 |
+
| Tool | Purpose |
|
| 8 |
+
|------|---------|
|
| 9 |
+
| **Next.js 14** | App Router, SSR/SSG |
|
| 10 |
+
| **TypeScript** | Full type safety |
|
| 11 |
+
| **Ant Design 5** | UI component system |
|
| 12 |
+
| **Framer Motion** | Animations & transitions |
|
| 13 |
+
| **React Three Fiber** | 3D particle explosion background |
|
| 14 |
+
| **Three.js** | 3D rendering engine |
|
| 15 |
+
|
| 16 |
+
## Getting Started
|
| 17 |
+
|
| 18 |
+
```bash
|
| 19 |
+
cd frontend
|
| 20 |
+
npm install
|
| 21 |
+
npm run dev
|
| 22 |
+
```
|
| 23 |
+
|
| 24 |
+
Open [http://localhost:3000](http://localhost:3000)
|
| 25 |
+
|
| 26 |
+
## Folder Structure
|
| 27 |
+
|
| 28 |
+
```
|
| 29 |
+
frontend/
|
| 30 |
+
βββ app/
|
| 31 |
+
β βββ layout.tsx # Root layout with Ant Design theme
|
| 32 |
+
β βββ page.tsx # Main page orchestrator
|
| 33 |
+
βββ components/
|
| 34 |
+
β βββ agents/
|
| 35 |
+
β β βββ AgentCard.tsx # Individual agent output card
|
| 36 |
+
β β βββ AgentPipeline.tsx # 3-agent pipeline layout
|
| 37 |
+
β βββ animations/
|
| 38 |
+
β β βββ ParticleBackground.tsx # 3D exploding Three.js scene
|
| 39 |
+
β βββ layout/
|
| 40 |
+
β β βββ Header.tsx # Fixed top navigation
|
| 41 |
+
β βββ ui/
|
| 42 |
+
β βββ HeroSection.tsx # Hero + project input
|
| 43 |
+
βββ lib/
|
| 44 |
+
β βββ api.ts # Backend API + mock mode
|
| 45 |
+
β βββ types.ts # Shared TypeScript types
|
| 46 |
+
βββ styles/
|
| 47 |
+
β βββ globals.css # CSS variables, fonts, base styles
|
| 48 |
+
βββ .env.local # Environment config
|
| 49 |
+
βββ package.json
|
| 50 |
+
```
|
| 51 |
+
|
| 52 |
+
## Environment Variables
|
| 53 |
+
|
| 54 |
+
```env
|
| 55 |
+
NEXT_PUBLIC_BACKEND_URL=http://localhost:8000 # FastAPI backend
|
| 56 |
+
NEXT_PUBLIC_MOCK_MODE=true # Enable mock responses
|
| 57 |
+
```
|
| 58 |
+
|
| 59 |
+
## Mock Mode
|
| 60 |
+
|
| 61 |
+
The frontend works fully without AMD credits using mock mode.
|
| 62 |
+
Realistic agent outputs are streamed with proper timing simulation.
|
| 63 |
+
|
| 64 |
+
Set `NEXT_PUBLIC_MOCK_MODE=false` and ensure `NEXT_PUBLIC_BACKEND_URL` points to a live backend once AMD credits are activated.
|
| 65 |
+
|
| 66 |
+
## Design System
|
| 67 |
+
|
| 68 |
+
- **Primary**: AMD Red `#E30913`
|
| 69 |
+
- **Accent**: Cyan `#00D4FF`, Gold `#FFB800`, Green `#00FF9C`
|
| 70 |
+
- **Font Display**: Orbitron
|
| 71 |
+
- **Font Body**: Rajdhani
|
| 72 |
+
- **Font Mono**: JetBrains Mono
|
| 73 |
+
- **Theme**: Dark β void black backgrounds with glowing accents
|
frontend/app/layout.tsx
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import type { Metadata } from 'next';
|
| 2 |
+
import AntdProvider from '../components/providers/AntdProvider';
|
| 3 |
+
import '../styles/globals.css';
|
| 4 |
+
|
| 5 |
+
export const metadata: Metadata = {
|
| 6 |
+
title: 'SystemForge AI β AMD Architecture Engine',
|
| 7 |
+
description:
|
| 8 |
+
'Autonomous multi-agent engine that plans, validates, and self-corrects production-grade software architectures.',
|
| 9 |
+
};
|
| 10 |
+
|
| 11 |
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
| 12 |
+
return (
|
| 13 |
+
<html lang="en">
|
| 14 |
+
<head>
|
| 15 |
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
| 16 |
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
|
| 17 |
+
<link
|
| 18 |
+
href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;600;700;900&family=JetBrains+Mono:wght@300;400;500;700&family=Rajdhani:wght@300;400;500;600;700&display=swap"
|
| 19 |
+
rel="stylesheet"
|
| 20 |
+
/>
|
| 21 |
+
</head>
|
| 22 |
+
<body>
|
| 23 |
+
<AntdProvider>{children}</AntdProvider>
|
| 24 |
+
</body>
|
| 25 |
+
</html>
|
| 26 |
+
);
|
| 27 |
+
}
|
frontend/app/page.tsx
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import React, { useState } from 'react';
|
| 4 |
+
|
| 5 |
+
import Navbar from '../components/ui/Navbar';
|
| 6 |
+
import WorkflowBuilder from '../components/workflow/WorkflowBuilder';
|
| 7 |
+
import BeforeAfterWorkflow from '../components/workflow/BeforeAfterWorkflow';
|
| 8 |
+
import WorkflowComparison from '../components/workflow/WorkflowComparison';
|
| 9 |
+
import AgentDecisionPanel from '../components/agents/AgentDecisionPanel';
|
| 10 |
+
import FinalArchitectureBlueprint from '../components/architecture/FinalArchitectureBlueprint';
|
| 11 |
+
import ArchitectureSummary from '../components/architecture/ArchitectureSummary';
|
| 12 |
+
import ParticleBackground from '../components/animations/ParticleBackground';
|
| 13 |
+
import LiveAgentThinking from '../components/agents/LiveAgentThinking';
|
| 14 |
+
import { EXAMPLE_WORKFLOWS } from '../lib/exampleWorkflows';
|
| 15 |
+
import {
|
| 16 |
+
generateWorkflowRedesign,
|
| 17 |
+
downloadArchitectureReport,
|
| 18 |
+
} from '../lib/api';
|
| 19 |
+
|
| 20 |
+
import type { SystemForgeResponse } from '../lib/types';
|
| 21 |
+
|
| 22 |
+
export default function HomePage() {
|
| 23 |
+
const [loading, setLoading] = useState(false);
|
| 24 |
+
|
| 25 |
+
const [systemData, setSystemData] =
|
| 26 |
+
useState<SystemForgeResponse | null>(null);
|
| 27 |
+
|
| 28 |
+
const [selectedWorkflow, setSelectedWorkflow] =
|
| 29 |
+
useState<typeof EXAMPLE_WORKFLOWS[0] | null>(null);
|
| 30 |
+
|
| 31 |
+
// generate LLM redesign
|
| 32 |
+
const handleGenerate = async (
|
| 33 |
+
workflowSteps: string[]
|
| 34 |
+
) => {
|
| 35 |
+
try {
|
| 36 |
+
setLoading(true);
|
| 37 |
+
console.log("Sending steps:", workflowSteps);
|
| 38 |
+
const result =
|
| 39 |
+
await generateWorkflowRedesign(
|
| 40 |
+
workflowSteps
|
| 41 |
+
);
|
| 42 |
+
console.log("API Result:", result);
|
| 43 |
+
setSystemData(result);
|
| 44 |
+
console.log("Received result:", result);
|
| 45 |
+
setTimeout(() => {
|
| 46 |
+
document
|
| 47 |
+
.getElementById('results')
|
| 48 |
+
?.scrollIntoView({
|
| 49 |
+
behavior: 'smooth',
|
| 50 |
+
block: 'start',
|
| 51 |
+
});
|
| 52 |
+
}, 400);
|
| 53 |
+
} catch (error) {
|
| 54 |
+
console.error(error);
|
| 55 |
+
alert(
|
| 56 |
+
'Failed to generate workflow redesign'
|
| 57 |
+
);
|
| 58 |
+
} finally {
|
| 59 |
+
setLoading(false);
|
| 60 |
+
}
|
| 61 |
+
};
|
| 62 |
+
|
| 63 |
+
const handleWorkflowChange = () => {
|
| 64 |
+
setSystemData(null);
|
| 65 |
+
};
|
| 66 |
+
|
| 67 |
+
const workflowToRender =
|
| 68 |
+
systemData?.workflowTransformation
|
| 69 |
+
? {
|
| 70 |
+
before: selectedWorkflow
|
| 71 |
+
? selectedWorkflow.before.map(step => step.label)
|
| 72 |
+
: systemData.workflowTransformation.before,
|
| 73 |
+
|
| 74 |
+
after: selectedWorkflow
|
| 75 |
+
? selectedWorkflow.after.map(step => step.label)
|
| 76 |
+
: systemData.workflowTransformation.after,
|
| 77 |
+
}
|
| 78 |
+
: null;
|
| 79 |
+
|
| 80 |
+
const handleWorkflowSelect = (
|
| 81 |
+
workflowId: string | null
|
| 82 |
+
) => {
|
| 83 |
+
if (!workflowId) {
|
| 84 |
+
setSelectedWorkflow(null);
|
| 85 |
+
return;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
const workflow =
|
| 89 |
+
EXAMPLE_WORKFLOWS.find(
|
| 90 |
+
(item) => item.id === workflowId
|
| 91 |
+
) || null;
|
| 92 |
+
|
| 93 |
+
setSelectedWorkflow(workflow);
|
| 94 |
+
};
|
| 95 |
+
|
| 96 |
+
const handleDownloadReport = async () => {
|
| 97 |
+
if (!systemData) {
|
| 98 |
+
alert('Generate architecture first');
|
| 99 |
+
return;
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
try {
|
| 103 |
+
const workflowSteps =
|
| 104 |
+
systemData.workflowTransformation.before;
|
| 105 |
+
|
| 106 |
+
await downloadArchitectureReport(
|
| 107 |
+
workflowSteps
|
| 108 |
+
);
|
| 109 |
+
} catch (error) {
|
| 110 |
+
console.error(error);
|
| 111 |
+
alert(
|
| 112 |
+
'Failed to download architecture report'
|
| 113 |
+
);
|
| 114 |
+
}
|
| 115 |
+
};
|
| 116 |
+
|
| 117 |
+
return (
|
| 118 |
+
<main
|
| 119 |
+
style={{
|
| 120 |
+
minHeight: '100vh',
|
| 121 |
+
background: '#03040a',
|
| 122 |
+
position: 'relative',
|
| 123 |
+
overflowX: 'hidden',
|
| 124 |
+
}}
|
| 125 |
+
>
|
| 126 |
+
<ParticleBackground />
|
| 127 |
+
<Navbar />
|
| 128 |
+
|
| 129 |
+
<section
|
| 130 |
+
style={{
|
| 131 |
+
position: 'relative',
|
| 132 |
+
zIndex: 10,
|
| 133 |
+
paddingTop: '120px',
|
| 134 |
+
paddingBottom: '80px',
|
| 135 |
+
}}
|
| 136 |
+
>
|
| 137 |
+
<WorkflowBuilder
|
| 138 |
+
onGenerate={handleGenerate}
|
| 139 |
+
isRunning={loading}
|
| 140 |
+
onWorkflowSelect={handleWorkflowSelect}
|
| 141 |
+
onWorkflowChange={handleWorkflowChange}
|
| 142 |
+
/>
|
| 143 |
+
</section>
|
| 144 |
+
|
| 145 |
+
{loading && (
|
| 146 |
+
<LiveAgentThinking />
|
| 147 |
+
)}
|
| 148 |
+
|
| 149 |
+
{systemData && !loading && (
|
| 150 |
+
<>
|
| 151 |
+
<section id="results">
|
| 152 |
+
{workflowToRender && (
|
| 153 |
+
<BeforeAfterWorkflow
|
| 154 |
+
data={workflowToRender}
|
| 155 |
+
/>
|
| 156 |
+
)}
|
| 157 |
+
|
| 158 |
+
<WorkflowComparison
|
| 159 |
+
data={systemData}
|
| 160 |
+
/>
|
| 161 |
+
|
| 162 |
+
<AgentDecisionPanel
|
| 163 |
+
architect={systemData.architect}
|
| 164 |
+
critic={systemData.critic}
|
| 165 |
+
refiner={systemData.refiner}
|
| 166 |
+
/>
|
| 167 |
+
|
| 168 |
+
<FinalArchitectureBlueprint
|
| 169 |
+
layers={systemData.architectureLayers}
|
| 170 |
+
/>
|
| 171 |
+
|
| 172 |
+
<ArchitectureSummary
|
| 173 |
+
metrics={systemData.finalMetrics}
|
| 174 |
+
onDownloadReport={handleDownloadReport}
|
| 175 |
+
/>
|
| 176 |
+
</section>
|
| 177 |
+
|
| 178 |
+
</>
|
| 179 |
+
)}
|
| 180 |
+
</main>
|
| 181 |
+
);
|
| 182 |
+
}
|
frontend/components/agents/AgentCard.tsx
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import React, { useEffect, useState, useRef } from 'react';
|
| 4 |
+
import { motion, AnimatePresence } from 'framer-motion';
|
| 5 |
+
import type { AgentOutput, AgentStatus } from '../../lib/types';
|
| 6 |
+
|
| 7 |
+
interface AgentCardProps {
|
| 8 |
+
output: AgentOutput;
|
| 9 |
+
index: number;
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
const AGENT_CONFIG = {
|
| 13 |
+
architect: {
|
| 14 |
+
num: '01', title: 'ARCHITECT', subtitle: 'System Design Agent',
|
| 15 |
+
color: '#00D4FF', glow: 'rgba(0,212,255,0.3)', subtle: 'rgba(0,212,255,0.06)',
|
| 16 |
+
icon: '⬑', persona: 'Senior Solutions Architect',
|
| 17 |
+
},
|
| 18 |
+
critic: {
|
| 19 |
+
num: '02', title: 'CRITIC', subtitle: 'SRE Review Agent',
|
| 20 |
+
color: '#FFB800', glow: 'rgba(255,184,0,0.3)', subtle: 'rgba(255,184,0,0.06)',
|
| 21 |
+
icon: 'β', persona: 'Principal Site Reliability Engineer',
|
| 22 |
+
},
|
| 23 |
+
refiner: {
|
| 24 |
+
num: '03', title: 'REFINER', subtitle: 'Self-Correction Agent',
|
| 25 |
+
color: '#00FF9C', glow: 'rgba(0,255,156,0.3)', subtle: 'rgba(0,255,156,0.06)',
|
| 26 |
+
icon: 'β', persona: 'Staff Platform Engineer',
|
| 27 |
+
},
|
| 28 |
+
};
|
| 29 |
+
|
| 30 |
+
const STATUS_LABELS: Record<AgentStatus, string> = {
|
| 31 |
+
idle: 'STANDBY', thinking: 'PROCESSING', complete: 'COMPLETE', error: 'ERROR',
|
| 32 |
+
};
|
| 33 |
+
|
| 34 |
+
// βββ Inline markdown renderer ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 35 |
+
function renderInline(text: string, color: string): React.ReactNode {
|
| 36 |
+
const parts = text.split(/(\*\*[^*]+\*\*|`[^`]+`)/g);
|
| 37 |
+
return parts.map((part, i) => {
|
| 38 |
+
if (part.startsWith('**') && part.endsWith('**')) {
|
| 39 |
+
return <strong key={i} style={{ color: '#F0F0FF', fontWeight: 700 }}>{part.slice(2, -2)}</strong>;
|
| 40 |
+
}
|
| 41 |
+
if (part.startsWith('`') && part.endsWith('`')) {
|
| 42 |
+
return (
|
| 43 |
+
<code key={i} style={{ color, background: 'rgba(255,255,255,0.06)', padding: '1px 5px', borderRadius: 2, fontSize: '0.75rem' }}>
|
| 44 |
+
{part.slice(1, -1)}
|
| 45 |
+
</code>
|
| 46 |
+
);
|
| 47 |
+
}
|
| 48 |
+
return part;
|
| 49 |
+
});
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
function MarkdownDisplay({ content, color }: { content: string; color: string }) {
|
| 53 |
+
return (
|
| 54 |
+
<div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.8rem', lineHeight: 1.7 }}>
|
| 55 |
+
{content.split('\n').map((line, i) => {
|
| 56 |
+
if (line.startsWith('# ')) {
|
| 57 |
+
return (
|
| 58 |
+
<div key={i} style={{ fontFamily: 'var(--font-display)', fontSize: '1rem', fontWeight: 700, color, marginBottom: '0.75rem', marginTop: i > 0 ? '1rem' : 0, letterSpacing: '0.05em' }}>
|
| 59 |
+
{line.replace(/^# /, '')}
|
| 60 |
+
</div>
|
| 61 |
+
);
|
| 62 |
+
}
|
| 63 |
+
if (line.startsWith('## ')) {
|
| 64 |
+
return (
|
| 65 |
+
<div key={i} style={{ fontFamily: 'var(--font-display)', fontSize: '0.8rem', fontWeight: 600, color: '#F0F0FF', marginTop: '1rem', marginBottom: '0.5rem', letterSpacing: '0.1em', borderBottom: '1px solid rgba(255,255,255,0.06)', paddingBottom: '4px' }}>
|
| 66 |
+
{line.replace(/^## /, '')}
|
| 67 |
+
</div>
|
| 68 |
+
);
|
| 69 |
+
}
|
| 70 |
+
if (line.startsWith('### ')) {
|
| 71 |
+
return (
|
| 72 |
+
<div key={i} style={{ fontSize: '0.75rem', fontWeight: 600, color: '#AAAACC', marginTop: '0.75rem', marginBottom: '0.25rem' }}>
|
| 73 |
+
{line.replace(/^### /, '')}
|
| 74 |
+
</div>
|
| 75 |
+
);
|
| 76 |
+
}
|
| 77 |
+
if (line.startsWith('- ') || line.startsWith('* ')) {
|
| 78 |
+
return (
|
| 79 |
+
<div key={i} style={{ display: 'flex', gap: '8px', marginBottom: '2px', paddingLeft: '8px' }}>
|
| 80 |
+
<span style={{ color, flexShrink: 0 }}>βΈ</span>
|
| 81 |
+
<span style={{ color: '#C0C0D8' }}>{renderInline(line.replace(/^[-*] /, ''), color)}</span>
|
| 82 |
+
</div>
|
| 83 |
+
);
|
| 84 |
+
}
|
| 85 |
+
if (line === '') return <div key={i} style={{ height: '0.4rem' }} />;
|
| 86 |
+
return <div key={i} style={{ color: '#B0B0C8', marginBottom: '1px' }}>{renderInline(line, color)}</div>;
|
| 87 |
+
})}
|
| 88 |
+
</div>
|
| 89 |
+
);
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
function ThinkingIndicator({ color }: { color: string }) {
|
| 93 |
+
return (
|
| 94 |
+
<div>
|
| 95 |
+
<div style={{ display: 'flex', gap: '4px', alignItems: 'center', marginBottom: '1rem' }}>
|
| 96 |
+
{[0, 1, 2, 3, 4].map((i) => (
|
| 97 |
+
<motion.div
|
| 98 |
+
key={i}
|
| 99 |
+
animate={{ scaleY: [0.4, 1.4, 0.4] }}
|
| 100 |
+
transition={{ duration: 0.8, repeat: Infinity, delay: i * 0.1 }}
|
| 101 |
+
style={{ width: 3, height: 18, borderRadius: 2, background: color, transformOrigin: 'center', opacity: 0.7 }}
|
| 102 |
+
/>
|
| 103 |
+
))}
|
| 104 |
+
<span style={{ fontFamily: 'var(--font-mono)', fontSize: '0.65rem', color: '#555577', marginLeft: '8px', letterSpacing: '0.1em' }}>
|
| 105 |
+
Agent reasoning...
|
| 106 |
+
</span>
|
| 107 |
+
</div>
|
| 108 |
+
{[70, 55, 85, 45, 65].map((w, i) => (
|
| 109 |
+
<motion.div
|
| 110 |
+
key={i}
|
| 111 |
+
animate={{ opacity: [0.15, 0.4, 0.15] }}
|
| 112 |
+
transition={{ duration: 1.5, repeat: Infinity, delay: i * 0.2 }}
|
| 113 |
+
style={{ height: 8, width: `${w}%`, borderRadius: 2, background: 'rgba(255,255,255,0.05)', marginBottom: '8px' }}
|
| 114 |
+
/>
|
| 115 |
+
))}
|
| 116 |
+
</div>
|
| 117 |
+
);
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
// βββ Main component βββββββββββββββββββββββοΏ½οΏ½βββββββββββββββββββββββββββββββββββ
|
| 121 |
+
export default function AgentCard({ output, index }: AgentCardProps) {
|
| 122 |
+
const config = AGENT_CONFIG[output.agent];
|
| 123 |
+
const [displayedContent, setDisplayedContent] = useState('');
|
| 124 |
+
const streamRef = useRef<NodeJS.Timeout | null>(null);
|
| 125 |
+
|
| 126 |
+
useEffect(() => {
|
| 127 |
+
if (output.status !== 'complete' || !output.content) {
|
| 128 |
+
setDisplayedContent('');
|
| 129 |
+
return;
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
// Reset and start streaming
|
| 133 |
+
setDisplayedContent('');
|
| 134 |
+
let char = 0;
|
| 135 |
+
const full = output.content;
|
| 136 |
+
|
| 137 |
+
streamRef.current = setInterval(() => {
|
| 138 |
+
char += 8;
|
| 139 |
+
setDisplayedContent(full.slice(0, char));
|
| 140 |
+
if (char >= full.length) {
|
| 141 |
+
setDisplayedContent(full);
|
| 142 |
+
if (streamRef.current) clearInterval(streamRef.current);
|
| 143 |
+
}
|
| 144 |
+
}, 10);
|
| 145 |
+
|
| 146 |
+
return () => { if (streamRef.current) clearInterval(streamRef.current); };
|
| 147 |
+
}, [output.status, output.content]);
|
| 148 |
+
|
| 149 |
+
const isThinking = output.status === 'thinking';
|
| 150 |
+
const isComplete = output.status === 'complete';
|
| 151 |
+
|
| 152 |
+
return (
|
| 153 |
+
<motion.div
|
| 154 |
+
initial={{ opacity: 0, x: index % 2 === 0 ? -40 : 40, y: 20 }}
|
| 155 |
+
animate={{ opacity: 1, x: 0, y: 0 }}
|
| 156 |
+
transition={{ delay: index * 0.15, duration: 0.6, ease: [0.16, 1, 0.3, 1] }}
|
| 157 |
+
style={{
|
| 158 |
+
position: 'relative',
|
| 159 |
+
border: `1px solid ${isComplete ? config.color + '40' : 'rgba(255,255,255,0.06)'}`,
|
| 160 |
+
borderRadius: 4,
|
| 161 |
+
overflow: 'hidden',
|
| 162 |
+
background: isComplete ? config.subtle : 'rgba(13,13,26,0.6)',
|
| 163 |
+
backdropFilter: 'blur(20px)',
|
| 164 |
+
transition: 'border 0.5s ease, background 0.5s ease, box-shadow 0.5s ease',
|
| 165 |
+
boxShadow: isComplete ? `0 0 40px ${config.glow}, 0 0 80px ${config.glow}22` : 'none',
|
| 166 |
+
}}
|
| 167 |
+
>
|
| 168 |
+
{/* Scan line when thinking */}
|
| 169 |
+
{isThinking && (
|
| 170 |
+
<motion.div
|
| 171 |
+
animate={{ top: ['0%', '100%'] }}
|
| 172 |
+
transition={{ duration: 1.5, repeat: Infinity, ease: 'linear' }}
|
| 173 |
+
style={{
|
| 174 |
+
position: 'absolute', left: 0, right: 0, height: '2px',
|
| 175 |
+
background: `linear-gradient(90deg, transparent, ${config.color}, transparent)`,
|
| 176 |
+
zIndex: 5,
|
| 177 |
+
}}
|
| 178 |
+
/>
|
| 179 |
+
)}
|
| 180 |
+
|
| 181 |
+
{/* Header */}
|
| 182 |
+
<div
|
| 183 |
+
style={{
|
| 184 |
+
display: 'flex', alignItems: 'center', justifyContent: 'space-between',
|
| 185 |
+
padding: '1rem 1.25rem',
|
| 186 |
+
borderBottom: '1px solid rgba(255,255,255,0.04)',
|
| 187 |
+
background: 'rgba(0,0,0,0.2)',
|
| 188 |
+
}}
|
| 189 |
+
>
|
| 190 |
+
<div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
|
| 191 |
+
<div
|
| 192 |
+
style={{
|
| 193 |
+
width: 40, height: 40,
|
| 194 |
+
border: `1px solid ${config.color}50`,
|
| 195 |
+
borderRadius: 4,
|
| 196 |
+
display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
|
| 197 |
+
background: `${config.color}10`,
|
| 198 |
+
}}
|
| 199 |
+
>
|
| 200 |
+
<span style={{ fontFamily: 'var(--font-mono)', fontSize: '0.55rem', color: config.color, letterSpacing: '0.1em' }}>{config.num}</span>
|
| 201 |
+
<span style={{ fontSize: '0.9rem', lineHeight: 1 }}>{config.icon}</span>
|
| 202 |
+
</div>
|
| 203 |
+
<div>
|
| 204 |
+
<div style={{ fontFamily: 'var(--font-display)', fontSize: '0.9rem', fontWeight: 700, color: config.color, letterSpacing: '0.15em' }}>
|
| 205 |
+
{config.title}
|
| 206 |
+
</div>
|
| 207 |
+
<div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.6rem', color: '#8888AA', letterSpacing: '0.08em', marginTop: 1 }}>
|
| 208 |
+
{config.persona}
|
| 209 |
+
</div>
|
| 210 |
+
</div>
|
| 211 |
+
</div>
|
| 212 |
+
|
| 213 |
+
{/* Status badge */}
|
| 214 |
+
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
| 215 |
+
{output.duration && isComplete && (
|
| 216 |
+
<span style={{ fontFamily: 'var(--font-mono)', fontSize: '0.6rem', color: '#444466' }}>
|
| 217 |
+
{(output.duration / 1000).toFixed(1)}s
|
| 218 |
+
</span>
|
| 219 |
+
)}
|
| 220 |
+
<motion.div
|
| 221 |
+
animate={isThinking ? { opacity: [1, 0.3, 1] } : {}}
|
| 222 |
+
transition={{ duration: 0.8, repeat: Infinity }}
|
| 223 |
+
style={{
|
| 224 |
+
display: 'flex', alignItems: 'center', gap: '5px',
|
| 225 |
+
padding: '3px 8px', borderRadius: 2,
|
| 226 |
+
border: `1px solid ${isComplete ? config.color + '50' : isThinking ? 'rgba(255,255,255,0.15)' : 'rgba(255,255,255,0.06)'}`,
|
| 227 |
+
background: isComplete ? `${config.color}15` : 'transparent',
|
| 228 |
+
}}
|
| 229 |
+
>
|
| 230 |
+
<div
|
| 231 |
+
style={{
|
| 232 |
+
width: 5, height: 5, borderRadius: '50%',
|
| 233 |
+
background: isComplete ? config.color : isThinking ? '#FFB800' : '#444466',
|
| 234 |
+
boxShadow: isComplete ? `0 0 8px ${config.color}` : isThinking ? '0 0 8px #FFB800' : 'none',
|
| 235 |
+
}}
|
| 236 |
+
/>
|
| 237 |
+
<span style={{ fontFamily: 'var(--font-mono)', fontSize: '0.55rem', letterSpacing: '0.15em', color: isComplete ? config.color : isThinking ? '#FFB800' : '#444466' }}>
|
| 238 |
+
{STATUS_LABELS[output.status]}
|
| 239 |
+
</span>
|
| 240 |
+
</motion.div>
|
| 241 |
+
</div>
|
| 242 |
+
</div>
|
| 243 |
+
|
| 244 |
+
{/* Body */}
|
| 245 |
+
<div style={{ padding: '1.25rem', minHeight: '200px' }}>
|
| 246 |
+
<AnimatePresence mode="wait">
|
| 247 |
+
{isThinking && (
|
| 248 |
+
<motion.div key="thinking" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}>
|
| 249 |
+
<ThinkingIndicator color={config.color} />
|
| 250 |
+
</motion.div>
|
| 251 |
+
)}
|
| 252 |
+
{isComplete && (
|
| 253 |
+
<motion.div key="content" initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 0.4 }}>
|
| 254 |
+
<MarkdownDisplay content={displayedContent} color={config.color} />
|
| 255 |
+
</motion.div>
|
| 256 |
+
)}
|
| 257 |
+
{output.status === 'idle' && (
|
| 258 |
+
<motion.div
|
| 259 |
+
key="idle"
|
| 260 |
+
initial={{ opacity: 0 }}
|
| 261 |
+
animate={{ opacity: 1 }}
|
| 262 |
+
style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '160px', flexDirection: 'column', gap: '12px' }}
|
| 263 |
+
>
|
| 264 |
+
<div style={{ width: 48, height: 48, border: `1px solid ${config.color}20`, borderRadius: 4, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '1.5rem', opacity: 0.3 }}>
|
| 265 |
+
{config.icon}
|
| 266 |
+
</div>
|
| 267 |
+
<span style={{ fontFamily: 'var(--font-mono)', fontSize: '0.65rem', color: '#333355', letterSpacing: '0.15em' }}>
|
| 268 |
+
AWAITING_ACTIVATION
|
| 269 |
+
</span>
|
| 270 |
+
</motion.div>
|
| 271 |
+
)}
|
| 272 |
+
{output.status === 'error' && (
|
| 273 |
+
<motion.div key="error" initial={{ opacity: 0 }} animate={{ opacity: 1 }}
|
| 274 |
+
style={{ padding: '1rem', background: 'rgba(227,9,19,0.08)', border: '1px solid rgba(227,9,19,0.2)', borderRadius: 4 }}
|
| 275 |
+
>
|
| 276 |
+
<div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.75rem', color: '#E30913', marginBottom: '0.5rem' }}>ERROR</div>
|
| 277 |
+
<div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.7rem', color: '#8888AA' }}>{output.content}</div>
|
| 278 |
+
</motion.div>
|
| 279 |
+
)}
|
| 280 |
+
</AnimatePresence>
|
| 281 |
+
</div>
|
| 282 |
+
</motion.div>
|
| 283 |
+
);
|
| 284 |
+
}
|
frontend/components/agents/AgentDecisionPanel.tsx
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import React from 'react';
|
| 4 |
+
import { motion } from 'framer-motion';
|
| 5 |
+
import type { AgentDecision } from '../../lib/types';
|
| 6 |
+
|
| 7 |
+
interface AgentDecisionPanelProps {
|
| 8 |
+
architect: AgentDecision;
|
| 9 |
+
critic: AgentDecision;
|
| 10 |
+
refiner: AgentDecision;
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
interface AgentCardData {
|
| 14 |
+
id: string;
|
| 15 |
+
role: string;
|
| 16 |
+
color: string;
|
| 17 |
+
data: AgentDecision;
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
function DecisionCard({
|
| 21 |
+
item,
|
| 22 |
+
index,
|
| 23 |
+
}: {
|
| 24 |
+
item: AgentCardData;
|
| 25 |
+
index: number;
|
| 26 |
+
}) {
|
| 27 |
+
return (
|
| 28 |
+
<motion.div
|
| 29 |
+
initial={{ opacity: 0, y: 24 }}
|
| 30 |
+
animate={{ opacity: 1, y: 0 }}
|
| 31 |
+
transition={{
|
| 32 |
+
delay: index * 0.12,
|
| 33 |
+
duration: 0.55,
|
| 34 |
+
}}
|
| 35 |
+
whileHover={{
|
| 36 |
+
y: -4,
|
| 37 |
+
}}
|
| 38 |
+
style={{
|
| 39 |
+
border: `1px solid ${item.color}20`,
|
| 40 |
+
background: `${item.color}05`,
|
| 41 |
+
borderRadius: 10,
|
| 42 |
+
padding: '2rem',
|
| 43 |
+
backdropFilter: 'blur(14px)',
|
| 44 |
+
boxShadow: `0 0 30px ${item.color}08`,
|
| 45 |
+
}}
|
| 46 |
+
>
|
| 47 |
+
{/* Header */}
|
| 48 |
+
<div
|
| 49 |
+
style={{
|
| 50 |
+
display: 'flex',
|
| 51 |
+
alignItems: 'flex-start',
|
| 52 |
+
justifyContent: 'space-between',
|
| 53 |
+
gap: '1rem',
|
| 54 |
+
marginBottom: '1.5rem',
|
| 55 |
+
}}
|
| 56 |
+
>
|
| 57 |
+
<div>
|
| 58 |
+
<div
|
| 59 |
+
style={{
|
| 60 |
+
fontFamily: 'var(--font-mono)',
|
| 61 |
+
fontSize: '0.72rem',
|
| 62 |
+
color: item.color,
|
| 63 |
+
letterSpacing: '0.22em',
|
| 64 |
+
marginBottom: '0.45rem',
|
| 65 |
+
}}
|
| 66 |
+
>
|
| 67 |
+
{item.id} Β· {item.role}
|
| 68 |
+
</div>
|
| 69 |
+
|
| 70 |
+
<div
|
| 71 |
+
style={{
|
| 72 |
+
fontFamily: 'var(--font-display)',
|
| 73 |
+
fontSize: '1rem',
|
| 74 |
+
color: '#F0F0FF',
|
| 75 |
+
letterSpacing: '0.08em',
|
| 76 |
+
marginBottom: '0.35rem',
|
| 77 |
+
}}
|
| 78 |
+
>
|
| 79 |
+
{item.data.title}
|
| 80 |
+
</div>
|
| 81 |
+
|
| 82 |
+
<div
|
| 83 |
+
style={{
|
| 84 |
+
color: item.color,
|
| 85 |
+
fontSize: '0.95rem',
|
| 86 |
+
fontWeight: 500,
|
| 87 |
+
}}
|
| 88 |
+
>
|
| 89 |
+
{item.data.subtitle}
|
| 90 |
+
</div>
|
| 91 |
+
</div>
|
| 92 |
+
|
| 93 |
+
<div
|
| 94 |
+
style={{
|
| 95 |
+
minWidth: 56,
|
| 96 |
+
height: 56,
|
| 97 |
+
borderRadius: 8,
|
| 98 |
+
border: `1px solid ${item.color}30`,
|
| 99 |
+
display: 'flex',
|
| 100 |
+
alignItems: 'center',
|
| 101 |
+
justifyContent: 'center',
|
| 102 |
+
fontFamily: 'var(--font-display)',
|
| 103 |
+
fontSize: '1rem',
|
| 104 |
+
color: item.color,
|
| 105 |
+
background: `${item.color}08`,
|
| 106 |
+
}}
|
| 107 |
+
>
|
| 108 |
+
{item.id}
|
| 109 |
+
</div>
|
| 110 |
+
</div>
|
| 111 |
+
|
| 112 |
+
{/* Decisions */}
|
| 113 |
+
<div>
|
| 114 |
+
<div
|
| 115 |
+
style={{
|
| 116 |
+
fontFamily: 'var(--font-mono)',
|
| 117 |
+
fontSize: '0.68rem',
|
| 118 |
+
color: item.color,
|
| 119 |
+
letterSpacing: '0.18em',
|
| 120 |
+
marginBottom: '0.9rem',
|
| 121 |
+
}}
|
| 122 |
+
>
|
| 123 |
+
KEY DECISIONS
|
| 124 |
+
</div>
|
| 125 |
+
|
| 126 |
+
<div
|
| 127 |
+
style={{
|
| 128 |
+
display: 'flex',
|
| 129 |
+
flexDirection: 'column',
|
| 130 |
+
gap: '0.8rem',
|
| 131 |
+
}}
|
| 132 |
+
>
|
| 133 |
+
{item.data.decisions.map((decision, i) => (
|
| 134 |
+
<div
|
| 135 |
+
key={i}
|
| 136 |
+
style={{
|
| 137 |
+
display: 'flex',
|
| 138 |
+
gap: '0.8rem',
|
| 139 |
+
alignItems: 'flex-start',
|
| 140 |
+
}}
|
| 141 |
+
>
|
| 142 |
+
<span
|
| 143 |
+
style={{
|
| 144 |
+
color: item.color,
|
| 145 |
+
fontSize: '0.8rem',
|
| 146 |
+
marginTop: '2px',
|
| 147 |
+
}}
|
| 148 |
+
>
|
| 149 |
+
β
|
| 150 |
+
</span>
|
| 151 |
+
|
| 152 |
+
<div
|
| 153 |
+
style={{
|
| 154 |
+
color: '#F0F0FF',
|
| 155 |
+
fontSize: '0.92rem',
|
| 156 |
+
lineHeight: 1.6,
|
| 157 |
+
}}
|
| 158 |
+
>
|
| 159 |
+
{decision}
|
| 160 |
+
</div>
|
| 161 |
+
</div>
|
| 162 |
+
))}
|
| 163 |
+
</div>
|
| 164 |
+
</div>
|
| 165 |
+
</motion.div>
|
| 166 |
+
);
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
export default function AgentDecisionPanel({
|
| 170 |
+
architect,
|
| 171 |
+
critic,
|
| 172 |
+
refiner,
|
| 173 |
+
}: AgentDecisionPanelProps) {
|
| 174 |
+
const agentCards: AgentCardData[] = [
|
| 175 |
+
{
|
| 176 |
+
id: '01',
|
| 177 |
+
role: 'ARCHITECT',
|
| 178 |
+
color: '#00D4FF',
|
| 179 |
+
data: architect,
|
| 180 |
+
},
|
| 181 |
+
{
|
| 182 |
+
id: '02',
|
| 183 |
+
role: 'CRITIC',
|
| 184 |
+
color: '#FFB800',
|
| 185 |
+
data: critic,
|
| 186 |
+
},
|
| 187 |
+
{
|
| 188 |
+
id: '03',
|
| 189 |
+
role: 'REFINER',
|
| 190 |
+
color: '#00FF9C',
|
| 191 |
+
data: refiner,
|
| 192 |
+
},
|
| 193 |
+
];
|
| 194 |
+
|
| 195 |
+
return (
|
| 196 |
+
<section
|
| 197 |
+
id="agent-intelligence"
|
| 198 |
+
style={{
|
| 199 |
+
position: 'relative',
|
| 200 |
+
zIndex: 10,
|
| 201 |
+
width: '100%',
|
| 202 |
+
padding: '5rem 2rem',
|
| 203 |
+
}}
|
| 204 |
+
>
|
| 205 |
+
<div
|
| 206 |
+
style={{
|
| 207 |
+
maxWidth: 1400,
|
| 208 |
+
margin: '0 auto',
|
| 209 |
+
}}
|
| 210 |
+
>
|
| 211 |
+
{/* Section Header */}
|
| 212 |
+
<motion.div
|
| 213 |
+
initial={{ opacity: 0, y: 18 }}
|
| 214 |
+
animate={{ opacity: 1, y: 0 }}
|
| 215 |
+
transition={{ duration: 0.55 }}
|
| 216 |
+
style={{
|
| 217 |
+
textAlign: 'center',
|
| 218 |
+
marginBottom: '3.5rem',
|
| 219 |
+
}}
|
| 220 |
+
>
|
| 221 |
+
<div
|
| 222 |
+
style={{
|
| 223 |
+
fontFamily: 'var(--font-mono)',
|
| 224 |
+
fontSize: '0.75rem',
|
| 225 |
+
color: '#E30913',
|
| 226 |
+
letterSpacing: '0.26em',
|
| 227 |
+
marginBottom: '0.8rem',
|
| 228 |
+
}}
|
| 229 |
+
>
|
| 230 |
+
MULTI-AGENT REASONING ENGINE
|
| 231 |
+
</div>
|
| 232 |
+
|
| 233 |
+
<h2
|
| 234 |
+
style={{
|
| 235 |
+
fontFamily: 'var(--font-display)',
|
| 236 |
+
fontSize: 'clamp(2rem, 4vw, 3.8rem)',
|
| 237 |
+
color: '#F0F0FF',
|
| 238 |
+
marginBottom: '1rem',
|
| 239 |
+
}}
|
| 240 |
+
>
|
| 241 |
+
Agent Decision Intelligence
|
| 242 |
+
</h2>
|
| 243 |
+
|
| 244 |
+
<p
|
| 245 |
+
style={{
|
| 246 |
+
maxWidth: 780,
|
| 247 |
+
margin: '0 auto',
|
| 248 |
+
color: '#8888AA',
|
| 249 |
+
fontSize: '1rem',
|
| 250 |
+
lineHeight: 1.75,
|
| 251 |
+
}}
|
| 252 |
+
>
|
| 253 |
+
SystemForge separates architecture generation
|
| 254 |
+
into specialized reasoning agents. Each agent
|
| 255 |
+
performs focused analysis: system design,
|
| 256 |
+
risk detection, and production hardening.
|
| 257 |
+
</p>
|
| 258 |
+
</motion.div>
|
| 259 |
+
|
| 260 |
+
{/* Cards */}
|
| 261 |
+
<div
|
| 262 |
+
style={{
|
| 263 |
+
display: 'grid',
|
| 264 |
+
gridTemplateColumns:
|
| 265 |
+
'repeat(auto-fit, minmax(340px, 1fr))',
|
| 266 |
+
gap: '1.6rem',
|
| 267 |
+
}}
|
| 268 |
+
>
|
| 269 |
+
{agentCards.map((item, index) => (
|
| 270 |
+
<DecisionCard
|
| 271 |
+
key={index}
|
| 272 |
+
item={item}
|
| 273 |
+
index={index}
|
| 274 |
+
/>
|
| 275 |
+
))}
|
| 276 |
+
</div>
|
| 277 |
+
</div>
|
| 278 |
+
</section>
|
| 279 |
+
);
|
| 280 |
+
}
|
frontend/components/agents/AgentPipeline.tsx
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import { motion } from 'framer-motion';
|
| 4 |
+
import type { AgentOutput } from '../../lib/types';
|
| 5 |
+
import AgentCard from './AgentCard';
|
| 6 |
+
|
| 7 |
+
interface AgentPipelineProps {
|
| 8 |
+
outputs: AgentOutput[];
|
| 9 |
+
isRunning: boolean;
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
export default function AgentPipeline({ outputs, isRunning }: AgentPipelineProps) {
|
| 13 |
+
const hasOutput = outputs.some((o) => o.status !== 'idle');
|
| 14 |
+
const allComplete = outputs.every((o) => o.status === 'complete') && outputs.length === 3;
|
| 15 |
+
|
| 16 |
+
return (
|
| 17 |
+
<motion.section
|
| 18 |
+
initial={{ opacity: 0, y: 40 }}
|
| 19 |
+
animate={{ opacity: hasOutput ? 1 : 0, y: hasOutput ? 0 : 40 }}
|
| 20 |
+
transition={{ duration: 0.7, ease: [0.16, 1, 0.3, 1] }}
|
| 21 |
+
style={{
|
| 22 |
+
position: 'relative',
|
| 23 |
+
zIndex: 10,
|
| 24 |
+
padding: '0 2rem 6rem',
|
| 25 |
+
maxWidth: '1400px',
|
| 26 |
+
margin: '0 auto',
|
| 27 |
+
}}
|
| 28 |
+
>
|
| 29 |
+
{/* Section header */}
|
| 30 |
+
<div
|
| 31 |
+
style={{
|
| 32 |
+
display: 'flex',
|
| 33 |
+
alignItems: 'center',
|
| 34 |
+
justifyContent: 'center',
|
| 35 |
+
gap: '1rem',
|
| 36 |
+
marginBottom: '2.5rem',
|
| 37 |
+
}}
|
| 38 |
+
>
|
| 39 |
+
<div
|
| 40 |
+
style={{
|
| 41 |
+
flex: 1,
|
| 42 |
+
height: 1,
|
| 43 |
+
background: 'linear-gradient(90deg, transparent, rgba(227,9,19,0.3))',
|
| 44 |
+
}}
|
| 45 |
+
/>
|
| 46 |
+
<div
|
| 47 |
+
style={{
|
| 48 |
+
fontFamily: 'var(--font-mono)',
|
| 49 |
+
fontSize: '0.65rem',
|
| 50 |
+
color: '#E30913',
|
| 51 |
+
letterSpacing: '0.3em',
|
| 52 |
+
whiteSpace: 'nowrap',
|
| 53 |
+
display: 'flex',
|
| 54 |
+
alignItems: 'center',
|
| 55 |
+
gap: '8px',
|
| 56 |
+
}}
|
| 57 |
+
>
|
| 58 |
+
{isRunning && (
|
| 59 |
+
<motion.div
|
| 60 |
+
animate={{ opacity: [1, 0.3, 1] }}
|
| 61 |
+
transition={{ duration: 0.6, repeat: Infinity }}
|
| 62 |
+
style={{
|
| 63 |
+
width: 6,
|
| 64 |
+
height: 6,
|
| 65 |
+
borderRadius: '50%',
|
| 66 |
+
background: '#E30913',
|
| 67 |
+
boxShadow: '0 0 10px rgba(227,9,19,0.8)',
|
| 68 |
+
}}
|
| 69 |
+
/>
|
| 70 |
+
)}
|
| 71 |
+
SELF-CORRECTION PIPELINE
|
| 72 |
+
</div>
|
| 73 |
+
<div
|
| 74 |
+
style={{
|
| 75 |
+
flex: 1,
|
| 76 |
+
height: 1,
|
| 77 |
+
background: 'linear-gradient(90deg, rgba(227,9,19,0.3), transparent)',
|
| 78 |
+
}}
|
| 79 |
+
/>
|
| 80 |
+
</div>
|
| 81 |
+
|
| 82 |
+
{/* Agent Cards Grid */}
|
| 83 |
+
<div
|
| 84 |
+
style={{
|
| 85 |
+
display: 'grid',
|
| 86 |
+
gridTemplateColumns: 'repeat(auto-fit, minmax(360px, 1fr))',
|
| 87 |
+
gap: '1.5rem',
|
| 88 |
+
}}
|
| 89 |
+
>
|
| 90 |
+
{outputs.map((output, i) => (
|
| 91 |
+
<AgentCard key={output.agent} output={output} index={i} />
|
| 92 |
+
))}
|
| 93 |
+
</div>
|
| 94 |
+
|
| 95 |
+
{/* Flow complete banner */}
|
| 96 |
+
{allComplete && (
|
| 97 |
+
<motion.div
|
| 98 |
+
initial={{ opacity: 0, scale: 0.95 }}
|
| 99 |
+
animate={{ opacity: 1, scale: 1 }}
|
| 100 |
+
transition={{ delay: 0.3, duration: 0.6 }}
|
| 101 |
+
style={{
|
| 102 |
+
marginTop: '2rem',
|
| 103 |
+
padding: '1.25rem 2rem',
|
| 104 |
+
border: '1px solid rgba(0,255,156,0.25)',
|
| 105 |
+
borderRadius: 4,
|
| 106 |
+
background: 'rgba(0,255,156,0.04)',
|
| 107 |
+
display: 'flex',
|
| 108 |
+
alignItems: 'center',
|
| 109 |
+
justifyContent: 'space-between',
|
| 110 |
+
flexWrap: 'wrap',
|
| 111 |
+
gap: '1rem',
|
| 112 |
+
}}
|
| 113 |
+
>
|
| 114 |
+
<div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
|
| 115 |
+
<motion.div
|
| 116 |
+
animate={{ scale: [1, 1.15, 1] }}
|
| 117 |
+
transition={{ duration: 1.5, repeat: Infinity }}
|
| 118 |
+
style={{
|
| 119 |
+
width: 8,
|
| 120 |
+
height: 8,
|
| 121 |
+
borderRadius: '50%',
|
| 122 |
+
background: '#00FF9C',
|
| 123 |
+
boxShadow: '0 0 15px rgba(0,255,156,0.6)',
|
| 124 |
+
}}
|
| 125 |
+
/>
|
| 126 |
+
<span
|
| 127 |
+
style={{
|
| 128 |
+
fontFamily: 'var(--font-display)',
|
| 129 |
+
fontSize: '0.8rem',
|
| 130 |
+
color: '#00FF9C',
|
| 131 |
+
letterSpacing: '0.15em',
|
| 132 |
+
}}
|
| 133 |
+
>
|
| 134 |
+
ARCHITECTURE SELF-CORRECTION COMPLETE
|
| 135 |
+
</span>
|
| 136 |
+
</div>
|
| 137 |
+
<div
|
| 138 |
+
style={{
|
| 139 |
+
fontFamily: 'var(--font-mono)',
|
| 140 |
+
fontSize: '0.65rem',
|
| 141 |
+
color: '#8888AA',
|
| 142 |
+
letterSpacing: '0.1em',
|
| 143 |
+
}}
|
| 144 |
+
>
|
| 145 |
+
Powered by AMD ROCm + Qwen2.5 + vLLM
|
| 146 |
+
</div>
|
| 147 |
+
</motion.div>
|
| 148 |
+
)}
|
| 149 |
+
</motion.section>
|
| 150 |
+
);
|
| 151 |
+
}
|
frontend/components/agents/LiveAgentThinking.tsx
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import React, {
|
| 4 |
+
useEffect,
|
| 5 |
+
useState,
|
| 6 |
+
} from 'react';
|
| 7 |
+
|
| 8 |
+
const AGENTS = [
|
| 9 |
+
{
|
| 10 |
+
icon: 'β‘',
|
| 11 |
+
title: 'SYSTEMS ARCHITECT',
|
| 12 |
+
message:
|
| 13 |
+
'Designing production-grade architecture...',
|
| 14 |
+
color: '#00d4ff',
|
| 15 |
+
},
|
| 16 |
+
{
|
| 17 |
+
icon: 'β ',
|
| 18 |
+
title: 'INFRASTRUCTURE CRITIC',
|
| 19 |
+
message:
|
| 20 |
+
'Finding failure points and bottlenecks...',
|
| 21 |
+
color: '#f59e0b',
|
| 22 |
+
},
|
| 23 |
+
{
|
| 24 |
+
icon: 'π‘',
|
| 25 |
+
title: 'PRODUCTION REFINER',
|
| 26 |
+
message:
|
| 27 |
+
'Hardening reliability and recovery paths...',
|
| 28 |
+
color: '#10b981',
|
| 29 |
+
},
|
| 30 |
+
{
|
| 31 |
+
icon: 'π',
|
| 32 |
+
title: 'EXECUTIVE SUMMARY',
|
| 33 |
+
message:
|
| 34 |
+
'Calculating ROI and deployment readiness...',
|
| 35 |
+
color: '#8b5cf6',
|
| 36 |
+
},
|
| 37 |
+
];
|
| 38 |
+
|
| 39 |
+
export default function LiveAgentThinking() {
|
| 40 |
+
const [activeIndex, setActiveIndex] =
|
| 41 |
+
useState(0);
|
| 42 |
+
|
| 43 |
+
useEffect(() => {
|
| 44 |
+
const interval = setInterval(() => {
|
| 45 |
+
setActiveIndex((prev) =>
|
| 46 |
+
prev < AGENTS.length - 1
|
| 47 |
+
? prev + 1
|
| 48 |
+
: prev
|
| 49 |
+
);
|
| 50 |
+
}, 1800);
|
| 51 |
+
|
| 52 |
+
return () =>
|
| 53 |
+
clearInterval(interval);
|
| 54 |
+
}, []);
|
| 55 |
+
|
| 56 |
+
return (
|
| 57 |
+
<section
|
| 58 |
+
style={{
|
| 59 |
+
maxWidth: '1200px',
|
| 60 |
+
margin: '0 auto',
|
| 61 |
+
padding: '60px 20px',
|
| 62 |
+
}}
|
| 63 |
+
>
|
| 64 |
+
<h2
|
| 65 |
+
style={{
|
| 66 |
+
fontSize: '42px',
|
| 67 |
+
fontWeight: 800,
|
| 68 |
+
textAlign: 'center',
|
| 69 |
+
color: '#fff',
|
| 70 |
+
marginBottom: '16px',
|
| 71 |
+
}}
|
| 72 |
+
>
|
| 73 |
+
AI Agents Are Thinking
|
| 74 |
+
</h2>
|
| 75 |
+
|
| 76 |
+
<p
|
| 77 |
+
style={{
|
| 78 |
+
textAlign: 'center',
|
| 79 |
+
color: '#94a3b8',
|
| 80 |
+
fontSize: '18px',
|
| 81 |
+
marginBottom: '50px',
|
| 82 |
+
}}
|
| 83 |
+
>
|
| 84 |
+
Multi-agent system redesigning
|
| 85 |
+
your workflow in real time
|
| 86 |
+
</p>
|
| 87 |
+
|
| 88 |
+
<div
|
| 89 |
+
style={{
|
| 90 |
+
display: 'grid',
|
| 91 |
+
gap: '20px',
|
| 92 |
+
}}
|
| 93 |
+
>
|
| 94 |
+
{AGENTS.map(
|
| 95 |
+
(agent, index) => {
|
| 96 |
+
const isActive =
|
| 97 |
+
index <= activeIndex;
|
| 98 |
+
|
| 99 |
+
return (
|
| 100 |
+
<div
|
| 101 |
+
key={
|
| 102 |
+
agent.title
|
| 103 |
+
}
|
| 104 |
+
style={{
|
| 105 |
+
padding:
|
| 106 |
+
'24px',
|
| 107 |
+
borderRadius:
|
| 108 |
+
'18px',
|
| 109 |
+
background:
|
| 110 |
+
'rgba(5,8,22,0.9)',
|
| 111 |
+
border: `1px solid ${isActive
|
| 112 |
+
? agent.color
|
| 113 |
+
: 'rgba(255,255,255,0.06)'
|
| 114 |
+
}`,
|
| 115 |
+
boxShadow:
|
| 116 |
+
isActive
|
| 117 |
+
? `0 0 30px ${agent.color}22`
|
| 118 |
+
: 'none',
|
| 119 |
+
opacity:
|
| 120 |
+
isActive
|
| 121 |
+
? 1
|
| 122 |
+
: 0.45,
|
| 123 |
+
transition:
|
| 124 |
+
'all 0.4s ease',
|
| 125 |
+
}}
|
| 126 |
+
>
|
| 127 |
+
<div
|
| 128 |
+
style={{
|
| 129 |
+
display:
|
| 130 |
+
'flex',
|
| 131 |
+
alignItems:
|
| 132 |
+
'center',
|
| 133 |
+
gap: '14px',
|
| 134 |
+
marginBottom:
|
| 135 |
+
'10px',
|
| 136 |
+
}}
|
| 137 |
+
>
|
| 138 |
+
<div
|
| 139 |
+
style={{
|
| 140 |
+
fontSize:
|
| 141 |
+
'28px',
|
| 142 |
+
}}
|
| 143 |
+
>
|
| 144 |
+
{
|
| 145 |
+
agent.icon
|
| 146 |
+
}
|
| 147 |
+
</div>
|
| 148 |
+
|
| 149 |
+
<div
|
| 150 |
+
style={{
|
| 151 |
+
fontSize:
|
| 152 |
+
'18px',
|
| 153 |
+
fontWeight: 700,
|
| 154 |
+
color:
|
| 155 |
+
'#fff',
|
| 156 |
+
}}
|
| 157 |
+
>
|
| 158 |
+
{
|
| 159 |
+
agent.title
|
| 160 |
+
}
|
| 161 |
+
</div>
|
| 162 |
+
</div>
|
| 163 |
+
|
| 164 |
+
<div
|
| 165 |
+
style={{
|
| 166 |
+
color:
|
| 167 |
+
'#cbd5e1',
|
| 168 |
+
fontSize:
|
| 169 |
+
'15px',
|
| 170 |
+
paddingLeft:
|
| 171 |
+
'42px',
|
| 172 |
+
}}
|
| 173 |
+
>
|
| 174 |
+
{
|
| 175 |
+
agent.message
|
| 176 |
+
}
|
| 177 |
+
</div>
|
| 178 |
+
</div>
|
| 179 |
+
);
|
| 180 |
+
}
|
| 181 |
+
)}
|
| 182 |
+
</div>
|
| 183 |
+
</section>
|
| 184 |
+
);
|
| 185 |
+
}
|
frontend/components/animations/ParticleBackground.tsx
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
export default function ParticleBackground() {
|
| 4 |
+
return (
|
| 5 |
+
<div className="cyber-background">
|
| 6 |
+
<div className="grid-overlay" />
|
| 7 |
+
<div className="glow glow-red" />
|
| 8 |
+
<div className="glow glow-blue" />
|
| 9 |
+
<div className="glow glow-green" />
|
| 10 |
+
<div className="scan-line" />
|
| 11 |
+
</div>
|
| 12 |
+
);
|
| 13 |
+
}
|
frontend/components/animations/ParticleCanvas.tsx
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import { useRef, useMemo } from 'react';
|
| 4 |
+
import { Canvas, useFrame } from '@react-three/fiber';
|
| 5 |
+
import { Points, PointMaterial } from '@react-three/drei';
|
| 6 |
+
import * as THREE from 'three';
|
| 7 |
+
|
| 8 |
+
function ParticleField({ isActive }: { isActive: boolean }) {
|
| 9 |
+
const pointsRef = useRef<THREE.Points>(null);
|
| 10 |
+
const velocitiesRef = useRef<Float32Array | null>(null);
|
| 11 |
+
const originalPositionsRef = useRef<Float32Array | null>(null);
|
| 12 |
+
|
| 13 |
+
const count = 1800;
|
| 14 |
+
|
| 15 |
+
const { positions } = useMemo(() => {
|
| 16 |
+
const positions = new Float32Array(count * 3);
|
| 17 |
+
const velocities = new Float32Array(count * 3);
|
| 18 |
+
|
| 19 |
+
for (let i = 0; i < count; i++) {
|
| 20 |
+
const theta = Math.random() * Math.PI * 2;
|
| 21 |
+
const phi = Math.acos(2 * Math.random() - 1);
|
| 22 |
+
const r = 2 + Math.random() * 3;
|
| 23 |
+
|
| 24 |
+
positions[i * 3] = r * Math.sin(phi) * Math.cos(theta);
|
| 25 |
+
positions[i * 3 + 1] = r * Math.sin(phi) * Math.sin(theta);
|
| 26 |
+
positions[i * 3 + 2] = r * Math.cos(phi);
|
| 27 |
+
|
| 28 |
+
velocities[i * 3] = (Math.random() - 0.5) * 0.02;
|
| 29 |
+
velocities[i * 3 + 1] = (Math.random() - 0.5) * 0.02;
|
| 30 |
+
velocities[i * 3 + 2] = (Math.random() - 0.5) * 0.02;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
velocitiesRef.current = velocities;
|
| 34 |
+
originalPositionsRef.current = positions.slice();
|
| 35 |
+
|
| 36 |
+
return { positions };
|
| 37 |
+
}, []);
|
| 38 |
+
|
| 39 |
+
useFrame((state) => {
|
| 40 |
+
if (!pointsRef.current) return;
|
| 41 |
+
|
| 42 |
+
const time = state.clock.elapsedTime;
|
| 43 |
+
const geometry = pointsRef.current.geometry;
|
| 44 |
+
const pos = geometry.attributes.position.array as Float32Array;
|
| 45 |
+
|
| 46 |
+
const original = originalPositionsRef.current!;
|
| 47 |
+
const velocity = velocitiesRef.current!;
|
| 48 |
+
|
| 49 |
+
for (let i = 0; i < count; i++) {
|
| 50 |
+
const index = i * 3;
|
| 51 |
+
|
| 52 |
+
if (isActive) {
|
| 53 |
+
pos[index] +=
|
| 54 |
+
velocity[index] *
|
| 55 |
+
(1 + Math.sin(time * 0.5 + i * 0.01) * 0.3);
|
| 56 |
+
|
| 57 |
+
pos[index + 1] +=
|
| 58 |
+
velocity[index + 1] *
|
| 59 |
+
(1 + Math.cos(time * 0.4 + i * 0.02) * 0.3);
|
| 60 |
+
|
| 61 |
+
pos[index + 2] +=
|
| 62 |
+
velocity[index + 2] *
|
| 63 |
+
(1 + Math.sin(time * 0.6 + i * 0.015) * 0.3);
|
| 64 |
+
|
| 65 |
+
const distance = Math.sqrt(
|
| 66 |
+
pos[index] ** 2 +
|
| 67 |
+
pos[index + 1] ** 2 +
|
| 68 |
+
pos[index + 2] ** 2
|
| 69 |
+
);
|
| 70 |
+
|
| 71 |
+
if (distance > 12) {
|
| 72 |
+
pos[index] *= 0.98;
|
| 73 |
+
pos[index + 1] *= 0.98;
|
| 74 |
+
pos[index + 2] *= 0.98;
|
| 75 |
+
}
|
| 76 |
+
} else {
|
| 77 |
+
pos[index] += (original[index] - pos[index]) * 0.03;
|
| 78 |
+
pos[index + 1] +=
|
| 79 |
+
(original[index + 1] - pos[index + 1]) * 0.03;
|
| 80 |
+
pos[index + 2] +=
|
| 81 |
+
(original[index + 2] - pos[index + 2]) * 0.03;
|
| 82 |
+
}
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
geometry.attributes.position.needsUpdate = true;
|
| 86 |
+
|
| 87 |
+
pointsRef.current.rotation.y = time * 0.04;
|
| 88 |
+
pointsRef.current.rotation.x = Math.sin(time * 0.02) * 0.1;
|
| 89 |
+
});
|
| 90 |
+
|
| 91 |
+
return (
|
| 92 |
+
<Points
|
| 93 |
+
ref={pointsRef}
|
| 94 |
+
positions={positions}
|
| 95 |
+
stride={3}
|
| 96 |
+
frustumCulled={false}
|
| 97 |
+
>
|
| 98 |
+
<PointMaterial
|
| 99 |
+
transparent
|
| 100 |
+
color="#00D4FF"
|
| 101 |
+
size={0.04}
|
| 102 |
+
sizeAttenuation
|
| 103 |
+
depthWrite={false}
|
| 104 |
+
blending={THREE.AdditiveBlending}
|
| 105 |
+
/>
|
| 106 |
+
</Points>
|
| 107 |
+
);
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
function RingSystem({ isActive }: { isActive: boolean }) {
|
| 111 |
+
const groupRef = useRef<THREE.Group>(null);
|
| 112 |
+
|
| 113 |
+
useFrame(({ clock }) => {
|
| 114 |
+
if (!groupRef.current) return;
|
| 115 |
+
|
| 116 |
+
const time = clock.elapsedTime;
|
| 117 |
+
|
| 118 |
+
groupRef.current.rotation.x = time * 0.15;
|
| 119 |
+
groupRef.current.rotation.z = time * 0.08;
|
| 120 |
+
|
| 121 |
+
const scale = isActive
|
| 122 |
+
? 1 + Math.sin(time * 2) * 0.08
|
| 123 |
+
: 1;
|
| 124 |
+
|
| 125 |
+
groupRef.current.scale.setScalar(scale);
|
| 126 |
+
});
|
| 127 |
+
|
| 128 |
+
return (
|
| 129 |
+
<group ref={groupRef}>
|
| 130 |
+
{[2.2, 3.1, 4.0].map((radius, index) => (
|
| 131 |
+
<mesh
|
| 132 |
+
key={index}
|
| 133 |
+
rotation={[
|
| 134 |
+
Math.PI / 2 + index * 0.4,
|
| 135 |
+
0,
|
| 136 |
+
index * 0.6,
|
| 137 |
+
]}
|
| 138 |
+
>
|
| 139 |
+
<torusGeometry args={[radius, 0.008, 16, 120]} />
|
| 140 |
+
<meshBasicMaterial
|
| 141 |
+
color={
|
| 142 |
+
index === 0
|
| 143 |
+
? '#E30913'
|
| 144 |
+
: index === 1
|
| 145 |
+
? '#00D4FF'
|
| 146 |
+
: '#FFB800'
|
| 147 |
+
}
|
| 148 |
+
transparent
|
| 149 |
+
opacity={isActive ? 0.7 : 0.25}
|
| 150 |
+
/>
|
| 151 |
+
</mesh>
|
| 152 |
+
))}
|
| 153 |
+
</group>
|
| 154 |
+
);
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
export default function ParticleCanvas({
|
| 158 |
+
isActive,
|
| 159 |
+
}: {
|
| 160 |
+
isActive: boolean;
|
| 161 |
+
}) {
|
| 162 |
+
return (
|
| 163 |
+
<Canvas
|
| 164 |
+
camera={{
|
| 165 |
+
position: [0, 0, 8],
|
| 166 |
+
fov: 60,
|
| 167 |
+
}}
|
| 168 |
+
gl={{
|
| 169 |
+
antialias: true,
|
| 170 |
+
alpha: true,
|
| 171 |
+
}}
|
| 172 |
+
style={{
|
| 173 |
+
background: 'transparent',
|
| 174 |
+
}}
|
| 175 |
+
>
|
| 176 |
+
<ambientLight intensity={0.3} />
|
| 177 |
+
|
| 178 |
+
<ParticleField isActive={isActive} />
|
| 179 |
+
|
| 180 |
+
<RingSystem isActive={isActive} />
|
| 181 |
+
</Canvas>
|
| 182 |
+
);
|
| 183 |
+
}
|
frontend/components/architecture/ArchitectureSummary.tsx
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import React from 'react';
|
| 4 |
+
import { motion } from 'framer-motion';
|
| 5 |
+
import type { FinalMetrics } from '../../lib/types';
|
| 6 |
+
|
| 7 |
+
interface ArchitectureSummaryProps {
|
| 8 |
+
metrics: FinalMetrics;
|
| 9 |
+
onDownloadReport: () => void;
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
interface MetricCardData {
|
| 13 |
+
label: string;
|
| 14 |
+
value: string;
|
| 15 |
+
subtitle: string;
|
| 16 |
+
color: string;
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
function MetricCard({
|
| 20 |
+
item,
|
| 21 |
+
index,
|
| 22 |
+
}: {
|
| 23 |
+
item: MetricCardData;
|
| 24 |
+
index: number;
|
| 25 |
+
}) {
|
| 26 |
+
return (
|
| 27 |
+
<motion.div
|
| 28 |
+
initial={{ opacity: 0, y: 22 }}
|
| 29 |
+
animate={{ opacity: 1, y: 0 }}
|
| 30 |
+
transition={{
|
| 31 |
+
delay: index * 0.08,
|
| 32 |
+
duration: 0.45,
|
| 33 |
+
}}
|
| 34 |
+
whileHover={{
|
| 35 |
+
y: -4,
|
| 36 |
+
}}
|
| 37 |
+
style={{
|
| 38 |
+
border: `1px solid ${item.color}18`,
|
| 39 |
+
background: `${item.color}05`,
|
| 40 |
+
borderRadius: 10,
|
| 41 |
+
padding: '1.8rem',
|
| 42 |
+
backdropFilter: 'blur(14px)',
|
| 43 |
+
boxShadow: `0 0 24px ${item.color}08`,
|
| 44 |
+
}}
|
| 45 |
+
>
|
| 46 |
+
<div
|
| 47 |
+
style={{
|
| 48 |
+
fontFamily: 'var(--font-display)',
|
| 49 |
+
fontSize: '2.2rem',
|
| 50 |
+
color: item.color,
|
| 51 |
+
marginBottom: '0.6rem',
|
| 52 |
+
lineHeight: 1,
|
| 53 |
+
}}
|
| 54 |
+
>
|
| 55 |
+
{item.value}
|
| 56 |
+
</div>
|
| 57 |
+
|
| 58 |
+
<div
|
| 59 |
+
style={{
|
| 60 |
+
fontFamily: 'var(--font-display)',
|
| 61 |
+
fontSize: '0.95rem',
|
| 62 |
+
color: '#F0F0FF',
|
| 63 |
+
marginBottom: '0.45rem',
|
| 64 |
+
letterSpacing: '0.04em',
|
| 65 |
+
}}
|
| 66 |
+
>
|
| 67 |
+
{item.label}
|
| 68 |
+
</div>
|
| 69 |
+
|
| 70 |
+
<div
|
| 71 |
+
style={{
|
| 72 |
+
color: '#8888AA',
|
| 73 |
+
fontSize: '0.9rem',
|
| 74 |
+
lineHeight: 1.6,
|
| 75 |
+
}}
|
| 76 |
+
>
|
| 77 |
+
{item.subtitle}
|
| 78 |
+
</div>
|
| 79 |
+
</motion.div>
|
| 80 |
+
);
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
export default function ArchitectureSummary({
|
| 84 |
+
metrics,
|
| 85 |
+
onDownloadReport,
|
| 86 |
+
}: ArchitectureSummaryProps) {
|
| 87 |
+
const metricCards: MetricCardData[] = [
|
| 88 |
+
{
|
| 89 |
+
label: 'Deployment Readiness',
|
| 90 |
+
value: metrics.deploymentReadiness,
|
| 91 |
+
subtitle: 'Production readiness score',
|
| 92 |
+
color: '#00FF9C',
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
label: 'Automation Potential',
|
| 96 |
+
value: metrics.automationPotential,
|
| 97 |
+
subtitle: 'Operational bottlenecks removed',
|
| 98 |
+
color: '#00D4FF',
|
| 99 |
+
},
|
| 100 |
+
{
|
| 101 |
+
label: 'Risk Score',
|
| 102 |
+
value: metrics.riskScore,
|
| 103 |
+
subtitle: 'System vulnerability evaluation',
|
| 104 |
+
color: '#FFB800',
|
| 105 |
+
},
|
| 106 |
+
{
|
| 107 |
+
label: 'Architecture Confidence',
|
| 108 |
+
value: metrics.architectureConfidence,
|
| 109 |
+
subtitle: 'Validated architecture confidence',
|
| 110 |
+
color: '#A020F0',
|
| 111 |
+
},
|
| 112 |
+
];
|
| 113 |
+
|
| 114 |
+
return (
|
| 115 |
+
<section
|
| 116 |
+
id="amd-inference"
|
| 117 |
+
style={{
|
| 118 |
+
position: 'relative',
|
| 119 |
+
zIndex: 10,
|
| 120 |
+
width: '100%',
|
| 121 |
+
padding: '4rem 2rem 6rem',
|
| 122 |
+
}}
|
| 123 |
+
>
|
| 124 |
+
<div
|
| 125 |
+
style={{
|
| 126 |
+
maxWidth: 1400,
|
| 127 |
+
margin: '0 auto',
|
| 128 |
+
}}
|
| 129 |
+
>
|
| 130 |
+
{/* Header */}
|
| 131 |
+
<motion.div
|
| 132 |
+
initial={{ opacity: 0, y: 18 }}
|
| 133 |
+
animate={{ opacity: 1, y: 0 }}
|
| 134 |
+
transition={{ duration: 0.55 }}
|
| 135 |
+
style={{
|
| 136 |
+
textAlign: 'center',
|
| 137 |
+
marginBottom: '3rem',
|
| 138 |
+
}}
|
| 139 |
+
>
|
| 140 |
+
<div
|
| 141 |
+
style={{
|
| 142 |
+
fontFamily: 'var(--font-mono)',
|
| 143 |
+
fontSize: '0.75rem',
|
| 144 |
+
color: '#00D4FF',
|
| 145 |
+
letterSpacing: '0.24em',
|
| 146 |
+
marginBottom: '0.8rem',
|
| 147 |
+
}}
|
| 148 |
+
>
|
| 149 |
+
ARCHITECTURE OUTCOME SUMMARY
|
| 150 |
+
</div>
|
| 151 |
+
|
| 152 |
+
<h2
|
| 153 |
+
style={{
|
| 154 |
+
fontFamily: 'var(--font-display)',
|
| 155 |
+
fontSize: 'clamp(2rem, 4vw, 3.4rem)',
|
| 156 |
+
color: '#F0F0FF',
|
| 157 |
+
marginBottom: '1rem',
|
| 158 |
+
}}
|
| 159 |
+
>
|
| 160 |
+
Final System Impact
|
| 161 |
+
</h2>
|
| 162 |
+
|
| 163 |
+
<p
|
| 164 |
+
style={{
|
| 165 |
+
maxWidth: 760,
|
| 166 |
+
margin: '0 auto',
|
| 167 |
+
color: '#8888AA',
|
| 168 |
+
fontSize: '1rem',
|
| 169 |
+
lineHeight: 1.75,
|
| 170 |
+
}}
|
| 171 |
+
>
|
| 172 |
+
SystemForge evaluates architectural improvements
|
| 173 |
+
beyond diagrams. The platform measures reliability,
|
| 174 |
+
scalability, workflow efficiency, and deployment
|
| 175 |
+
readiness to provide a complete engineering outcome.
|
| 176 |
+
</p>
|
| 177 |
+
</motion.div>
|
| 178 |
+
|
| 179 |
+
{/* Metrics Grid */}
|
| 180 |
+
<div
|
| 181 |
+
style={{
|
| 182 |
+
display: 'grid',
|
| 183 |
+
gridTemplateColumns:
|
| 184 |
+
'repeat(auto-fit, minmax(260px, 1fr))',
|
| 185 |
+
gap: '1.4rem',
|
| 186 |
+
marginBottom: '3rem',
|
| 187 |
+
}}
|
| 188 |
+
>
|
| 189 |
+
{metricCards.map((item, index) => (
|
| 190 |
+
<MetricCard
|
| 191 |
+
key={index}
|
| 192 |
+
item={item}
|
| 193 |
+
index={index}
|
| 194 |
+
/>
|
| 195 |
+
))}
|
| 196 |
+
</div>
|
| 197 |
+
|
| 198 |
+
{/* Closing Block */}
|
| 199 |
+
<motion.div
|
| 200 |
+
initial={{ opacity: 0 }}
|
| 201 |
+
animate={{ opacity: 1 }}
|
| 202 |
+
transition={{
|
| 203 |
+
delay: 0.35,
|
| 204 |
+
duration: 0.6,
|
| 205 |
+
}}
|
| 206 |
+
style={{
|
| 207 |
+
border: '1px solid rgba(0,212,255,0.12)',
|
| 208 |
+
background: 'rgba(0,212,255,0.03)',
|
| 209 |
+
borderRadius: 10,
|
| 210 |
+
padding: '2.5rem',
|
| 211 |
+
textAlign: 'center',
|
| 212 |
+
}}
|
| 213 |
+
>
|
| 214 |
+
<div
|
| 215 |
+
style={{
|
| 216 |
+
fontFamily: 'var(--font-mono)',
|
| 217 |
+
fontSize: '0.72rem',
|
| 218 |
+
color: '#00D4FF',
|
| 219 |
+
letterSpacing: '0.22em',
|
| 220 |
+
marginBottom: '0.8rem',
|
| 221 |
+
}}
|
| 222 |
+
>
|
| 223 |
+
SYSTEMFORGE RESULT
|
| 224 |
+
</div>
|
| 225 |
+
|
| 226 |
+
<div
|
| 227 |
+
style={{
|
| 228 |
+
fontFamily: 'var(--font-display)',
|
| 229 |
+
fontSize: '1.1rem',
|
| 230 |
+
color: '#F0F0FF',
|
| 231 |
+
marginBottom: '0.8rem',
|
| 232 |
+
}}
|
| 233 |
+
>
|
| 234 |
+
Workflow Redesign + Production Validation
|
| 235 |
+
in One Engine
|
| 236 |
+
</div>
|
| 237 |
+
|
| 238 |
+
<p
|
| 239 |
+
style={{
|
| 240 |
+
maxWidth: 780,
|
| 241 |
+
margin: '0 auto',
|
| 242 |
+
color: '#8888AA',
|
| 243 |
+
lineHeight: 1.7,
|
| 244 |
+
fontSize: '0.95rem',
|
| 245 |
+
}}
|
| 246 |
+
>
|
| 247 |
+
The final output is not just a workflow redesign.
|
| 248 |
+
It is a production-grade system strategy with
|
| 249 |
+
measurable business impact, operational clarity,
|
| 250 |
+
and infrastructure confidence.
|
| 251 |
+
</p>
|
| 252 |
+
|
| 253 |
+
{/* Download Button INSIDE final card */}
|
| 254 |
+
<div
|
| 255 |
+
style={{
|
| 256 |
+
marginTop: '32px',
|
| 257 |
+
display: 'flex',
|
| 258 |
+
justifyContent: 'center',
|
| 259 |
+
}}
|
| 260 |
+
>
|
| 261 |
+
<button
|
| 262 |
+
onClick={onDownloadReport}
|
| 263 |
+
style={{
|
| 264 |
+
background:
|
| 265 |
+
'linear-gradient(135deg, #2563eb, #1d4ed8)',
|
| 266 |
+
color: '#fff',
|
| 267 |
+
border: 'none',
|
| 268 |
+
padding: '18px 42px',
|
| 269 |
+
borderRadius: '14px',
|
| 270 |
+
fontSize: '16px',
|
| 271 |
+
fontWeight: 700,
|
| 272 |
+
cursor: 'pointer',
|
| 273 |
+
boxShadow:
|
| 274 |
+
'0 12px 32px rgba(37,99,235,0.25)',
|
| 275 |
+
transition: 'all 0.3s ease',
|
| 276 |
+
}}
|
| 277 |
+
onMouseEnter={(e) => {
|
| 278 |
+
e.currentTarget.style.transform =
|
| 279 |
+
'translateY(-2px)';
|
| 280 |
+
}}
|
| 281 |
+
onMouseLeave={(e) => {
|
| 282 |
+
e.currentTarget.style.transform =
|
| 283 |
+
'translateY(0px)';
|
| 284 |
+
}}
|
| 285 |
+
>
|
| 286 |
+
Download Architecture Report
|
| 287 |
+
</button>
|
| 288 |
+
</div>
|
| 289 |
+
</motion.div>
|
| 290 |
+
</div>
|
| 291 |
+
</section>
|
| 292 |
+
);
|
| 293 |
+
}
|
frontend/components/architecture/FinalArchitectureBlueprint.tsx
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import React from 'react';
|
| 4 |
+
import { motion } from 'framer-motion';
|
| 5 |
+
import type { ArchitectureLayer } from '../../lib/types';
|
| 6 |
+
|
| 7 |
+
interface FinalArchitectureBlueprintProps {
|
| 8 |
+
layers: ArchitectureLayer[];
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
function LayerCard({
|
| 12 |
+
layer,
|
| 13 |
+
index,
|
| 14 |
+
}: {
|
| 15 |
+
layer: ArchitectureLayer;
|
| 16 |
+
index: number;
|
| 17 |
+
}) {
|
| 18 |
+
const colors = ['#00D4FF', '#FFB800', '#00FF9C', '#E30913'];
|
| 19 |
+
const color = colors[index % colors.length];
|
| 20 |
+
|
| 21 |
+
return (
|
| 22 |
+
<motion.div
|
| 23 |
+
initial={{ opacity: 0, y: 24 }}
|
| 24 |
+
animate={{ opacity: 1, y: 0 }}
|
| 25 |
+
transition={{
|
| 26 |
+
delay: index * 0.12,
|
| 27 |
+
duration: 0.55,
|
| 28 |
+
}}
|
| 29 |
+
whileHover={{
|
| 30 |
+
y: -4,
|
| 31 |
+
}}
|
| 32 |
+
style={{
|
| 33 |
+
border: `1px solid ${color}20`,
|
| 34 |
+
background: `${color}05`,
|
| 35 |
+
borderRadius: 10,
|
| 36 |
+
padding: '2rem',
|
| 37 |
+
backdropFilter: 'blur(14px)',
|
| 38 |
+
boxShadow: `0 0 30px ${color}08`,
|
| 39 |
+
}}
|
| 40 |
+
>
|
| 41 |
+
{/* Header */}
|
| 42 |
+
<div
|
| 43 |
+
style={{
|
| 44 |
+
marginBottom: '1.5rem',
|
| 45 |
+
}}
|
| 46 |
+
>
|
| 47 |
+
<div
|
| 48 |
+
style={{
|
| 49 |
+
fontFamily: 'var(--font-mono)',
|
| 50 |
+
fontSize: '0.72rem',
|
| 51 |
+
color,
|
| 52 |
+
letterSpacing: '0.22em',
|
| 53 |
+
marginBottom: '0.5rem',
|
| 54 |
+
}}
|
| 55 |
+
>
|
| 56 |
+
LAYER {String(index + 1).padStart(2, '0')}
|
| 57 |
+
</div>
|
| 58 |
+
|
| 59 |
+
<div
|
| 60 |
+
style={{
|
| 61 |
+
fontFamily: 'var(--font-display)',
|
| 62 |
+
fontSize: '1rem',
|
| 63 |
+
color: '#F0F0FF',
|
| 64 |
+
letterSpacing: '0.06em',
|
| 65 |
+
marginBottom: '0.5rem',
|
| 66 |
+
}}
|
| 67 |
+
>
|
| 68 |
+
{layer.title}
|
| 69 |
+
</div>
|
| 70 |
+
|
| 71 |
+
<div
|
| 72 |
+
style={{
|
| 73 |
+
color: '#8888AA',
|
| 74 |
+
fontSize: '0.92rem',
|
| 75 |
+
lineHeight: 1.6,
|
| 76 |
+
}}
|
| 77 |
+
>
|
| 78 |
+
{layer.description}
|
| 79 |
+
</div>
|
| 80 |
+
</div>
|
| 81 |
+
|
| 82 |
+
{/* Items */}
|
| 83 |
+
<div
|
| 84 |
+
style={{
|
| 85 |
+
display: 'flex',
|
| 86 |
+
flexDirection: 'column',
|
| 87 |
+
gap: '0.8rem',
|
| 88 |
+
}}
|
| 89 |
+
>
|
| 90 |
+
{layer.items.map((item, i) => (
|
| 91 |
+
<div
|
| 92 |
+
key={i}
|
| 93 |
+
style={{
|
| 94 |
+
display: 'flex',
|
| 95 |
+
gap: '0.8rem',
|
| 96 |
+
alignItems: 'flex-start',
|
| 97 |
+
}}
|
| 98 |
+
>
|
| 99 |
+
<span
|
| 100 |
+
style={{
|
| 101 |
+
color,
|
| 102 |
+
fontSize: '0.8rem',
|
| 103 |
+
marginTop: '2px',
|
| 104 |
+
}}
|
| 105 |
+
>
|
| 106 |
+
β
|
| 107 |
+
</span>
|
| 108 |
+
|
| 109 |
+
<div
|
| 110 |
+
style={{
|
| 111 |
+
color: '#F0F0FF',
|
| 112 |
+
fontSize: '0.92rem',
|
| 113 |
+
lineHeight: 1.6,
|
| 114 |
+
}}
|
| 115 |
+
>
|
| 116 |
+
{item}
|
| 117 |
+
</div>
|
| 118 |
+
</div>
|
| 119 |
+
))}
|
| 120 |
+
</div>
|
| 121 |
+
</motion.div>
|
| 122 |
+
);
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
export default function FinalArchitectureBlueprint({
|
| 126 |
+
layers,
|
| 127 |
+
}: FinalArchitectureBlueprintProps) {
|
| 128 |
+
return (
|
| 129 |
+
<section
|
| 130 |
+
id="architecture-blueprint"
|
| 131 |
+
style={{
|
| 132 |
+
position: 'relative',
|
| 133 |
+
zIndex: 10,
|
| 134 |
+
width: '100%',
|
| 135 |
+
padding: '5rem 2rem',
|
| 136 |
+
}}
|
| 137 |
+
>
|
| 138 |
+
<div
|
| 139 |
+
style={{
|
| 140 |
+
maxWidth: 1400,
|
| 141 |
+
margin: '0 auto',
|
| 142 |
+
}}
|
| 143 |
+
>
|
| 144 |
+
{/* Section Header */}
|
| 145 |
+
<motion.div
|
| 146 |
+
initial={{ opacity: 0, y: 18 }}
|
| 147 |
+
animate={{ opacity: 1, y: 0 }}
|
| 148 |
+
transition={{ duration: 0.55 }}
|
| 149 |
+
style={{
|
| 150 |
+
textAlign: 'center',
|
| 151 |
+
marginBottom: '3.5rem',
|
| 152 |
+
}}
|
| 153 |
+
>
|
| 154 |
+
<div
|
| 155 |
+
style={{
|
| 156 |
+
fontFamily: 'var(--font-mono)',
|
| 157 |
+
fontSize: '0.75rem',
|
| 158 |
+
color: '#E30913',
|
| 159 |
+
letterSpacing: '0.26em',
|
| 160 |
+
marginBottom: '0.8rem',
|
| 161 |
+
}}
|
| 162 |
+
>
|
| 163 |
+
PRODUCTION SYSTEM BLUEPRINT
|
| 164 |
+
</div>
|
| 165 |
+
|
| 166 |
+
<h2
|
| 167 |
+
style={{
|
| 168 |
+
fontFamily: 'var(--font-display)',
|
| 169 |
+
fontSize: 'clamp(2rem, 4vw, 3.8rem)',
|
| 170 |
+
color: '#F0F0FF',
|
| 171 |
+
marginBottom: '1rem',
|
| 172 |
+
}}
|
| 173 |
+
>
|
| 174 |
+
Final Architecture Blueprint
|
| 175 |
+
</h2>
|
| 176 |
+
|
| 177 |
+
<p
|
| 178 |
+
style={{
|
| 179 |
+
maxWidth: 820,
|
| 180 |
+
margin: '0 auto',
|
| 181 |
+
color: '#8888AA',
|
| 182 |
+
fontSize: '1rem',
|
| 183 |
+
lineHeight: 1.75,
|
| 184 |
+
}}
|
| 185 |
+
>
|
| 186 |
+
SystemForge produces a production-ready
|
| 187 |
+
architecture blueprint covering orchestration,
|
| 188 |
+
inference, infrastructure, observability,
|
| 189 |
+
deployment, and operational reliability.
|
| 190 |
+
</p>
|
| 191 |
+
</motion.div>
|
| 192 |
+
|
| 193 |
+
{/* Architecture Layers */}
|
| 194 |
+
<div
|
| 195 |
+
style={{
|
| 196 |
+
display: 'grid',
|
| 197 |
+
gridTemplateColumns:
|
| 198 |
+
'repeat(auto-fit, minmax(320px, 1fr))',
|
| 199 |
+
gap: '1.6rem',
|
| 200 |
+
}}
|
| 201 |
+
>
|
| 202 |
+
{layers.map((layer, index) => (
|
| 203 |
+
<LayerCard
|
| 204 |
+
key={index}
|
| 205 |
+
layer={layer}
|
| 206 |
+
index={index}
|
| 207 |
+
/>
|
| 208 |
+
))}
|
| 209 |
+
</div>
|
| 210 |
+
|
| 211 |
+
{/* Bottom Summary */}
|
| 212 |
+
<motion.div
|
| 213 |
+
initial={{ opacity: 0 }}
|
| 214 |
+
animate={{ opacity: 1 }}
|
| 215 |
+
transition={{
|
| 216 |
+
delay: 0.4,
|
| 217 |
+
duration: 0.6,
|
| 218 |
+
}}
|
| 219 |
+
style={{
|
| 220 |
+
marginTop: '3rem',
|
| 221 |
+
border: '1px solid rgba(227,9,19,0.16)',
|
| 222 |
+
background: 'rgba(227,9,19,0.03)',
|
| 223 |
+
borderRadius: 10,
|
| 224 |
+
padding: '2rem',
|
| 225 |
+
textAlign: 'center',
|
| 226 |
+
}}
|
| 227 |
+
>
|
| 228 |
+
<div
|
| 229 |
+
style={{
|
| 230 |
+
fontFamily: 'var(--font-mono)',
|
| 231 |
+
fontSize: '0.72rem',
|
| 232 |
+
color: '#E30913',
|
| 233 |
+
letterSpacing: '0.22em',
|
| 234 |
+
marginBottom: '0.8rem',
|
| 235 |
+
}}
|
| 236 |
+
>
|
| 237 |
+
FINAL OUTCOME
|
| 238 |
+
</div>
|
| 239 |
+
|
| 240 |
+
<div
|
| 241 |
+
style={{
|
| 242 |
+
fontFamily: 'var(--font-display)',
|
| 243 |
+
fontSize: '1.15rem',
|
| 244 |
+
color: '#F0F0FF',
|
| 245 |
+
marginBottom: '0.8rem',
|
| 246 |
+
}}
|
| 247 |
+
>
|
| 248 |
+
From Manual Operations β Production-Ready AI System
|
| 249 |
+
</div>
|
| 250 |
+
|
| 251 |
+
<p
|
| 252 |
+
style={{
|
| 253 |
+
color: '#8888AA',
|
| 254 |
+
maxWidth: 760,
|
| 255 |
+
margin: '0 auto',
|
| 256 |
+
lineHeight: 1.7,
|
| 257 |
+
fontSize: '0.95rem',
|
| 258 |
+
}}
|
| 259 |
+
>
|
| 260 |
+
Workflow redesign, architecture validation,
|
| 261 |
+
AI inference, and deployment-ready system
|
| 262 |
+
planning β all inside one engineering platform.
|
| 263 |
+
</p>
|
| 264 |
+
</motion.div>
|
| 265 |
+
</div>
|
| 266 |
+
</section>
|
| 267 |
+
);
|
| 268 |
+
}
|
frontend/components/layout/Header.tsx
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import { motion } from 'framer-motion';
|
| 4 |
+
|
| 5 |
+
export default function Header() {
|
| 6 |
+
return (
|
| 7 |
+
<motion.header
|
| 8 |
+
initial={{ opacity: 0, y: -20 }}
|
| 9 |
+
animate={{ opacity: 1, y: 0 }}
|
| 10 |
+
transition={{ duration: 0.6, ease: 'easeOut' }}
|
| 11 |
+
style={{
|
| 12 |
+
position: 'fixed',
|
| 13 |
+
top: 0,
|
| 14 |
+
left: 0,
|
| 15 |
+
right: 0,
|
| 16 |
+
zIndex: 100,
|
| 17 |
+
borderBottom: '1px solid rgba(227,9,19,0.15)',
|
| 18 |
+
backdropFilter: 'blur(20px)',
|
| 19 |
+
WebkitBackdropFilter: 'blur(20px)',
|
| 20 |
+
background: 'rgba(7,7,15,0.85)',
|
| 21 |
+
padding: '0 2rem',
|
| 22 |
+
height: '60px',
|
| 23 |
+
display: 'flex',
|
| 24 |
+
alignItems: 'center',
|
| 25 |
+
justifyContent: 'space-between',
|
| 26 |
+
}}
|
| 27 |
+
>
|
| 28 |
+
{/* Logo */}
|
| 29 |
+
<div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
|
| 30 |
+
<motion.div
|
| 31 |
+
animate={{ rotate: 360 }}
|
| 32 |
+
transition={{ duration: 8, repeat: Infinity, ease: 'linear' }}
|
| 33 |
+
style={{
|
| 34 |
+
width: 28,
|
| 35 |
+
height: 28,
|
| 36 |
+
border: '2px solid #E30913',
|
| 37 |
+
borderRadius: 4,
|
| 38 |
+
display: 'flex',
|
| 39 |
+
alignItems: 'center',
|
| 40 |
+
justifyContent: 'center',
|
| 41 |
+
}}
|
| 42 |
+
>
|
| 43 |
+
<div
|
| 44 |
+
style={{
|
| 45 |
+
width: 10,
|
| 46 |
+
height: 10,
|
| 47 |
+
background: '#E30913',
|
| 48 |
+
borderRadius: 2,
|
| 49 |
+
boxShadow: '0 0 12px rgba(227,9,19,0.8)',
|
| 50 |
+
}}
|
| 51 |
+
/>
|
| 52 |
+
</motion.div>
|
| 53 |
+
<div>
|
| 54 |
+
<div
|
| 55 |
+
style={{
|
| 56 |
+
fontFamily: 'var(--font-display)',
|
| 57 |
+
fontSize: '0.85rem',
|
| 58 |
+
fontWeight: 700,
|
| 59 |
+
color: '#F0F0FF',
|
| 60 |
+
letterSpacing: '0.12em',
|
| 61 |
+
}}
|
| 62 |
+
>
|
| 63 |
+
SYSTEM<span style={{ color: '#E30913' }}>FORGE</span>
|
| 64 |
+
</div>
|
| 65 |
+
<div
|
| 66 |
+
style={{
|
| 67 |
+
fontFamily: 'var(--font-mono)',
|
| 68 |
+
fontSize: '0.55rem',
|
| 69 |
+
color: '#8888AA',
|
| 70 |
+
letterSpacing: '0.2em',
|
| 71 |
+
marginTop: -2,
|
| 72 |
+
}}
|
| 73 |
+
>
|
| 74 |
+
AI ARCHITECTURE ENGINE
|
| 75 |
+
</div>
|
| 76 |
+
</div>
|
| 77 |
+
</div>
|
| 78 |
+
|
| 79 |
+
{/* Status pills */}
|
| 80 |
+
<div style={{ display: 'flex', alignItems: 'center', gap: '1.5rem' }}>
|
| 81 |
+
<StatusPill label="AMD ROCm" color="#E30913" />
|
| 82 |
+
<StatusPill label="Qwen 2.5" color="#00D4FF" />
|
| 83 |
+
<StatusPill label="vLLM" color="#00FF9C" pulse />
|
| 84 |
+
</div>
|
| 85 |
+
|
| 86 |
+
{/* AMD Badge */}
|
| 87 |
+
<div
|
| 88 |
+
style={{
|
| 89 |
+
fontFamily: 'var(--font-display)',
|
| 90 |
+
fontSize: '0.6rem',
|
| 91 |
+
fontWeight: 700,
|
| 92 |
+
letterSpacing: '0.15em',
|
| 93 |
+
color: '#E30913',
|
| 94 |
+
border: '1px solid rgba(227,9,19,0.4)',
|
| 95 |
+
padding: '4px 10px',
|
| 96 |
+
borderRadius: 2,
|
| 97 |
+
}}
|
| 98 |
+
>
|
| 99 |
+
AMD HACKATHON Β· TRACK 1
|
| 100 |
+
</div>
|
| 101 |
+
</motion.header>
|
| 102 |
+
);
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
function StatusPill({ label, color, pulse }: { label: string; color: string; pulse?: boolean }) {
|
| 106 |
+
return (
|
| 107 |
+
<div style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
|
| 108 |
+
<motion.div
|
| 109 |
+
animate={pulse ? { opacity: [1, 0.3, 1] } : {}}
|
| 110 |
+
transition={{ duration: 1.5, repeat: Infinity }}
|
| 111 |
+
style={{
|
| 112 |
+
width: 6,
|
| 113 |
+
height: 6,
|
| 114 |
+
borderRadius: '50%',
|
| 115 |
+
background: color,
|
| 116 |
+
boxShadow: `0 0 8px ${color}`,
|
| 117 |
+
}}
|
| 118 |
+
/>
|
| 119 |
+
<span
|
| 120 |
+
style={{
|
| 121 |
+
fontFamily: 'var(--font-mono)',
|
| 122 |
+
fontSize: '0.65rem',
|
| 123 |
+
color: '#8888AA',
|
| 124 |
+
letterSpacing: '0.08em',
|
| 125 |
+
}}
|
| 126 |
+
>
|
| 127 |
+
{label}
|
| 128 |
+
</span>
|
| 129 |
+
</div>
|
| 130 |
+
);
|
| 131 |
+
}
|
frontend/components/providers/AntdProvider.tsx
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import { ConfigProvider, theme } from 'antd';
|
| 4 |
+
import React from 'react';
|
| 5 |
+
|
| 6 |
+
const amdTheme = {
|
| 7 |
+
algorithm: theme.darkAlgorithm,
|
| 8 |
+
token: {
|
| 9 |
+
colorPrimary: '#E30913',
|
| 10 |
+
colorBgBase: '#07070F',
|
| 11 |
+
colorBgContainer: '#0D0D1A',
|
| 12 |
+
colorBgElevated: '#1A1A2E',
|
| 13 |
+
colorBorder: 'rgba(255,255,255,0.06)',
|
| 14 |
+
colorText: '#F0F0FF',
|
| 15 |
+
colorTextSecondary: '#8888AA',
|
| 16 |
+
fontFamily: "'Rajdhani', sans-serif",
|
| 17 |
+
borderRadius: 2,
|
| 18 |
+
wireframe: false,
|
| 19 |
+
},
|
| 20 |
+
components: {
|
| 21 |
+
Button: { colorPrimary: '#E30913', algorithm: true },
|
| 22 |
+
Input: {
|
| 23 |
+
colorBgContainer: '#0D0D1A',
|
| 24 |
+
activeBorderColor: '#E30913',
|
| 25 |
+
hoverBorderColor: 'rgba(227,9,19,0.5)',
|
| 26 |
+
},
|
| 27 |
+
},
|
| 28 |
+
};
|
| 29 |
+
|
| 30 |
+
export default function AntdProvider({ children }: { children: React.ReactNode }) {
|
| 31 |
+
return <ConfigProvider theme={amdTheme}>{children}</ConfigProvider>;
|
| 32 |
+
}
|
frontend/components/ui/HeroSection.tsx
ADDED
|
@@ -0,0 +1,369 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React from 'react';
|
| 2 |
+
import { motion } from 'framer-motion';
|
| 3 |
+
import WorkflowBuilder from '../workflow/WorkflowBuilder';
|
| 4 |
+
|
| 5 |
+
interface HeroSectionProps {
|
| 6 |
+
onSubmit: (workflowText: string) => void;
|
| 7 |
+
isRunning: boolean;
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
+
const EXAMPLE_WORKFLOWS = [
|
| 11 |
+
{
|
| 12 |
+
title: 'E-commerce Operations Chaos',
|
| 13 |
+
flow:
|
| 14 |
+
'Orders come from Shopify β Team manually updates inventory in Excel β Slack message sent to warehouse β Warehouse updates delivery status manually β Customer support manually handles delays',
|
| 15 |
+
},
|
| 16 |
+
{
|
| 17 |
+
title: 'Hospital Approval Workflow',
|
| 18 |
+
flow:
|
| 19 |
+
'Patient fills intake form β Reception manually verifies insurance β Doctor manually reviews reports β Lab sends PDF reports by email β Admin manually updates billing',
|
| 20 |
+
},
|
| 21 |
+
{
|
| 22 |
+
title: 'Hiring Workflow Mess',
|
| 23 |
+
flow:
|
| 24 |
+
'Resume comes from LinkedIn β HR manually shortlists candidates β Interview scheduling via WhatsApp β Feedback collected in Google Sheets β Offer approval delayed manually',
|
| 25 |
+
},
|
| 26 |
+
{
|
| 27 |
+
title: 'Startup Support Workflow',
|
| 28 |
+
flow:
|
| 29 |
+
'Customer submits issue β Support team checks CRM manually β Engineering gets pinged in Slack β Fix status tracked in Notion β Customer gets manual update email',
|
| 30 |
+
},
|
| 31 |
+
];
|
| 32 |
+
|
| 33 |
+
const containerVariants = {
|
| 34 |
+
hidden: {},
|
| 35 |
+
visible: {
|
| 36 |
+
transition: {
|
| 37 |
+
staggerChildren: 0.14,
|
| 38 |
+
},
|
| 39 |
+
},
|
| 40 |
+
};
|
| 41 |
+
|
| 42 |
+
const fadeUp = {
|
| 43 |
+
hidden: {
|
| 44 |
+
opacity: 0,
|
| 45 |
+
y: 30,
|
| 46 |
+
},
|
| 47 |
+
visible: {
|
| 48 |
+
opacity: 1,
|
| 49 |
+
y: 0,
|
| 50 |
+
transition: {
|
| 51 |
+
duration: 0.7,
|
| 52 |
+
ease: 'easeOut',
|
| 53 |
+
},
|
| 54 |
+
},
|
| 55 |
+
};
|
| 56 |
+
|
| 57 |
+
export default function HeroSection({
|
| 58 |
+
onSubmit,
|
| 59 |
+
isRunning,
|
| 60 |
+
}: HeroSectionProps) {
|
| 61 |
+
return (
|
| 62 |
+
<section
|
| 63 |
+
style={{
|
| 64 |
+
position: 'relative',
|
| 65 |
+
zIndex: 10,
|
| 66 |
+
minHeight: '100vh',
|
| 67 |
+
display: 'flex',
|
| 68 |
+
justifyContent: 'center',
|
| 69 |
+
padding: '120px 24px 80px',
|
| 70 |
+
}}
|
| 71 |
+
>
|
| 72 |
+
<motion.div
|
| 73 |
+
variants={containerVariants}
|
| 74 |
+
initial="hidden"
|
| 75 |
+
animate="visible"
|
| 76 |
+
style={{
|
| 77 |
+
width: '100%',
|
| 78 |
+
maxWidth: '1200px',
|
| 79 |
+
display: 'flex',
|
| 80 |
+
flexDirection: 'column',
|
| 81 |
+
alignItems: 'center',
|
| 82 |
+
}}
|
| 83 |
+
>
|
| 84 |
+
{/* EYEBROW */}
|
| 85 |
+
<motion.div
|
| 86 |
+
variants={fadeUp}
|
| 87 |
+
style={{
|
| 88 |
+
display: 'flex',
|
| 89 |
+
alignItems: 'center',
|
| 90 |
+
gap: '12px',
|
| 91 |
+
marginBottom: '28px',
|
| 92 |
+
}}
|
| 93 |
+
>
|
| 94 |
+
<div
|
| 95 |
+
style={{
|
| 96 |
+
width: 60,
|
| 97 |
+
height: 1,
|
| 98 |
+
background:
|
| 99 |
+
'linear-gradient(90deg, transparent, rgba(227,9,19,0.7))',
|
| 100 |
+
}}
|
| 101 |
+
/>
|
| 102 |
+
|
| 103 |
+
<span
|
| 104 |
+
style={{
|
| 105 |
+
fontFamily: 'var(--font-mono)',
|
| 106 |
+
fontSize: '0.72rem',
|
| 107 |
+
letterSpacing: '0.35em',
|
| 108 |
+
color: '#E30913',
|
| 109 |
+
}}
|
| 110 |
+
>
|
| 111 |
+
WORKFLOW REDESIGN ENGINE
|
| 112 |
+
</span>
|
| 113 |
+
|
| 114 |
+
<div
|
| 115 |
+
style={{
|
| 116 |
+
width: 60,
|
| 117 |
+
height: 1,
|
| 118 |
+
background:
|
| 119 |
+
'linear-gradient(90deg, rgba(227,9,19,0.7), transparent)',
|
| 120 |
+
}}
|
| 121 |
+
/>
|
| 122 |
+
</motion.div>
|
| 123 |
+
|
| 124 |
+
{/* TITLE */}
|
| 125 |
+
<motion.div
|
| 126 |
+
variants={fadeUp}
|
| 127 |
+
style={{
|
| 128 |
+
textAlign: 'center',
|
| 129 |
+
marginBottom: '28px',
|
| 130 |
+
}}
|
| 131 |
+
>
|
| 132 |
+
<h1
|
| 133 |
+
style={{
|
| 134 |
+
fontFamily: 'var(--font-display)',
|
| 135 |
+
fontSize: 'clamp(4rem, 10vw, 8rem)',
|
| 136 |
+
lineHeight: 0.95,
|
| 137 |
+
fontWeight: 900,
|
| 138 |
+
letterSpacing: '-0.03em',
|
| 139 |
+
marginBottom: '16px',
|
| 140 |
+
}}
|
| 141 |
+
>
|
| 142 |
+
<span style={{ color: '#F0F0FF' }}>
|
| 143 |
+
SYSTEM
|
| 144 |
+
</span>
|
| 145 |
+
|
| 146 |
+
<span
|
| 147 |
+
style={{
|
| 148 |
+
color: '#E30913',
|
| 149 |
+
textShadow:
|
| 150 |
+
'0 0 30px rgba(227,9,19,0.5), 0 0 80px rgba(227,9,19,0.25)',
|
| 151 |
+
}}
|
| 152 |
+
>
|
| 153 |
+
FORGE
|
| 154 |
+
</span>
|
| 155 |
+
</h1>
|
| 156 |
+
|
| 157 |
+
<div
|
| 158 |
+
style={{
|
| 159 |
+
fontFamily: 'var(--font-display)',
|
| 160 |
+
fontSize: 'clamp(1.5rem, 3vw, 2.6rem)',
|
| 161 |
+
color: '#8888AA',
|
| 162 |
+
letterSpacing: '0.08em',
|
| 163 |
+
}}
|
| 164 |
+
>
|
| 165 |
+
Messy Workflow β AI-Native Architecture
|
| 166 |
+
</div>
|
| 167 |
+
</motion.div>
|
| 168 |
+
|
| 169 |
+
{/* TAGLINE */}
|
| 170 |
+
<motion.p
|
| 171 |
+
variants={fadeUp}
|
| 172 |
+
style={{
|
| 173 |
+
maxWidth: '860px',
|
| 174 |
+
textAlign: 'center',
|
| 175 |
+
fontSize: 'clamp(1rem, 2vw, 1.25rem)',
|
| 176 |
+
lineHeight: 1.8,
|
| 177 |
+
color: '#8888AA',
|
| 178 |
+
marginBottom: '52px',
|
| 179 |
+
}}
|
| 180 |
+
>
|
| 181 |
+
Transform approvals, spreadsheets, manual handoffs, broken operations,
|
| 182 |
+
and disconnected systems into scalable production-grade AI workflows
|
| 183 |
+
powered by{' '}
|
| 184 |
+
<span
|
| 185 |
+
style={{
|
| 186 |
+
color: '#00D4FF',
|
| 187 |
+
textShadow:
|
| 188 |
+
'0 0 20px rgba(0,212,255,0.18)',
|
| 189 |
+
}}
|
| 190 |
+
>
|
| 191 |
+
AMD-accelerated Qwen models
|
| 192 |
+
</span>
|
| 193 |
+
.
|
| 194 |
+
</motion.p>
|
| 195 |
+
|
| 196 |
+
{/* AGENT FLOW */}
|
| 197 |
+
<motion.div
|
| 198 |
+
variants={fadeUp}
|
| 199 |
+
style={{
|
| 200 |
+
display: 'flex',
|
| 201 |
+
alignItems: 'center',
|
| 202 |
+
justifyContent: 'center',
|
| 203 |
+
flexWrap: 'wrap',
|
| 204 |
+
gap: '10px',
|
| 205 |
+
marginBottom: '56px',
|
| 206 |
+
}}
|
| 207 |
+
>
|
| 208 |
+
{[
|
| 209 |
+
{
|
| 210 |
+
num: '01',
|
| 211 |
+
title: 'ARCHITECT',
|
| 212 |
+
color: '#00D4FF',
|
| 213 |
+
},
|
| 214 |
+
{
|
| 215 |
+
num: '02',
|
| 216 |
+
title: 'CRITIC',
|
| 217 |
+
color: '#FFB800',
|
| 218 |
+
},
|
| 219 |
+
{
|
| 220 |
+
num: '03',
|
| 221 |
+
title: 'REFINER',
|
| 222 |
+
color: '#00FF9C',
|
| 223 |
+
},
|
| 224 |
+
].map((item, index) => (
|
| 225 |
+
<React.Fragment key={item.title}>
|
| 226 |
+
<motion.div
|
| 227 |
+
whileHover={{
|
| 228 |
+
scale: 1.03,
|
| 229 |
+
y: -2,
|
| 230 |
+
}}
|
| 231 |
+
style={{
|
| 232 |
+
padding: '14px 30px',
|
| 233 |
+
border: `1px solid ${item.color}30`,
|
| 234 |
+
background: `${item.color}08`,
|
| 235 |
+
borderRadius: 4,
|
| 236 |
+
minWidth: 190,
|
| 237 |
+
textAlign: 'center',
|
| 238 |
+
}}
|
| 239 |
+
>
|
| 240 |
+
<div
|
| 241 |
+
style={{
|
| 242 |
+
fontFamily: 'var(--font-mono)',
|
| 243 |
+
fontSize: '0.7rem',
|
| 244 |
+
color: item.color,
|
| 245 |
+
letterSpacing: '0.25em',
|
| 246 |
+
marginBottom: 4,
|
| 247 |
+
}}
|
| 248 |
+
>
|
| 249 |
+
{item.num}
|
| 250 |
+
</div>
|
| 251 |
+
|
| 252 |
+
<div
|
| 253 |
+
style={{
|
| 254 |
+
fontFamily: 'var(--font-display)',
|
| 255 |
+
fontSize: '0.95rem',
|
| 256 |
+
color: item.color,
|
| 257 |
+
letterSpacing: '0.18em',
|
| 258 |
+
}}
|
| 259 |
+
>
|
| 260 |
+
{item.title}
|
| 261 |
+
</div>
|
| 262 |
+
</motion.div>
|
| 263 |
+
|
| 264 |
+
{index < 2 && (
|
| 265 |
+
<div
|
| 266 |
+
style={{
|
| 267 |
+
color: '#444466',
|
| 268 |
+
fontSize: '1.2rem',
|
| 269 |
+
}}
|
| 270 |
+
>
|
| 271 |
+
β
|
| 272 |
+
</div>
|
| 273 |
+
)}
|
| 274 |
+
</React.Fragment>
|
| 275 |
+
))}
|
| 276 |
+
</motion.div>
|
| 277 |
+
|
| 278 |
+
{/* WORKFLOW BUILDER */}
|
| 279 |
+
<motion.div
|
| 280 |
+
variants={fadeUp}
|
| 281 |
+
style={{
|
| 282 |
+
width: '100%',
|
| 283 |
+
maxWidth: '980px',
|
| 284 |
+
marginBottom: '48px',
|
| 285 |
+
}}
|
| 286 |
+
>
|
| 287 |
+
<WorkflowBuilder
|
| 288 |
+
onGenerate={(steps: string[]) =>
|
| 289 |
+
onSubmit(steps.join(' β '))
|
| 290 |
+
}
|
| 291 |
+
isRunning={isRunning}
|
| 292 |
+
onWorkflowSelect={() => { }}
|
| 293 |
+
onWorkflowChange={() => { }}
|
| 294 |
+
/>
|
| 295 |
+
</motion.div>
|
| 296 |
+
|
| 297 |
+
{/* EXAMPLE WORKFLOWS */}
|
| 298 |
+
<motion.div
|
| 299 |
+
variants={fadeUp}
|
| 300 |
+
style={{
|
| 301 |
+
width: '100%',
|
| 302 |
+
maxWidth: '980px',
|
| 303 |
+
}}
|
| 304 |
+
>
|
| 305 |
+
<div
|
| 306 |
+
style={{
|
| 307 |
+
fontFamily: 'var(--font-mono)',
|
| 308 |
+
fontSize: '0.7rem',
|
| 309 |
+
letterSpacing: '0.28em',
|
| 310 |
+
color: '#444466',
|
| 311 |
+
marginBottom: '18px',
|
| 312 |
+
textAlign: 'center',
|
| 313 |
+
}}
|
| 314 |
+
>
|
| 315 |
+
EXAMPLE_MESSY_WORKFLOWS
|
| 316 |
+
</div>
|
| 317 |
+
|
| 318 |
+
<div
|
| 319 |
+
style={{
|
| 320 |
+
display: 'flex',
|
| 321 |
+
flexDirection: 'column',
|
| 322 |
+
gap: '18px',
|
| 323 |
+
}}
|
| 324 |
+
>
|
| 325 |
+
{EXAMPLE_WORKFLOWS.map((item, index) => (
|
| 326 |
+
<motion.div
|
| 327 |
+
key={index}
|
| 328 |
+
whileHover={{
|
| 329 |
+
y: -2,
|
| 330 |
+
}}
|
| 331 |
+
style={{
|
| 332 |
+
background:
|
| 333 |
+
'rgba(0,212,255,0.04)',
|
| 334 |
+
border:
|
| 335 |
+
'1px solid rgba(0,212,255,0.12)',
|
| 336 |
+
borderRadius: 4,
|
| 337 |
+
padding: '22px',
|
| 338 |
+
cursor: 'pointer',
|
| 339 |
+
}}
|
| 340 |
+
>
|
| 341 |
+
<div
|
| 342 |
+
style={{
|
| 343 |
+
fontFamily: 'var(--font-display)',
|
| 344 |
+
fontSize: '1.1rem',
|
| 345 |
+
color: '#00D4FF',
|
| 346 |
+
marginBottom: '12px',
|
| 347 |
+
}}
|
| 348 |
+
>
|
| 349 |
+
{item.title}
|
| 350 |
+
</div>
|
| 351 |
+
|
| 352 |
+
<div
|
| 353 |
+
style={{
|
| 354 |
+
fontFamily: 'var(--font-mono)',
|
| 355 |
+
fontSize: '0.88rem',
|
| 356 |
+
lineHeight: 1.8,
|
| 357 |
+
color: '#8888AA',
|
| 358 |
+
}}
|
| 359 |
+
>
|
| 360 |
+
{item.flow}
|
| 361 |
+
</div>
|
| 362 |
+
</motion.div>
|
| 363 |
+
))}
|
| 364 |
+
</div>
|
| 365 |
+
</motion.div>
|
| 366 |
+
</motion.div>
|
| 367 |
+
</section>
|
| 368 |
+
);
|
| 369 |
+
}
|
frontend/components/ui/Navbar.tsx
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import React from 'react';
|
| 4 |
+
import { motion } from 'framer-motion';
|
| 5 |
+
|
| 6 |
+
const navItems = [
|
| 7 |
+
{
|
| 8 |
+
label: 'Workflow Engine',
|
| 9 |
+
target: 'workflow-engine',
|
| 10 |
+
},
|
| 11 |
+
{
|
| 12 |
+
label: 'Agent Intelligence',
|
| 13 |
+
target: 'agent-intelligence',
|
| 14 |
+
},
|
| 15 |
+
{
|
| 16 |
+
label: 'Architecture Blueprint',
|
| 17 |
+
target: 'architecture-blueprint',
|
| 18 |
+
},
|
| 19 |
+
{
|
| 20 |
+
label: 'AMD Inference',
|
| 21 |
+
target: 'amd-inference',
|
| 22 |
+
},
|
| 23 |
+
];
|
| 24 |
+
|
| 25 |
+
export default function Navbar() {
|
| 26 |
+
const scrollToSection = (id: string) => {
|
| 27 |
+
const section = document.getElementById(id);
|
| 28 |
+
|
| 29 |
+
if (section) {
|
| 30 |
+
section.scrollIntoView({
|
| 31 |
+
behavior: 'smooth',
|
| 32 |
+
block: 'start',
|
| 33 |
+
});
|
| 34 |
+
}
|
| 35 |
+
};
|
| 36 |
+
|
| 37 |
+
return (
|
| 38 |
+
<header
|
| 39 |
+
style={{
|
| 40 |
+
position: 'fixed',
|
| 41 |
+
top: 0,
|
| 42 |
+
left: 0,
|
| 43 |
+
right: 0,
|
| 44 |
+
zIndex: 100,
|
| 45 |
+
backdropFilter: 'blur(20px)',
|
| 46 |
+
background: 'rgba(3, 4, 10, 0.75)',
|
| 47 |
+
borderBottom:
|
| 48 |
+
'1px solid rgba(255,255,255,0.04)',
|
| 49 |
+
}}
|
| 50 |
+
>
|
| 51 |
+
<div
|
| 52 |
+
style={{
|
| 53 |
+
maxWidth: '1400px',
|
| 54 |
+
margin: '0 auto',
|
| 55 |
+
padding: '18px 28px',
|
| 56 |
+
display: 'flex',
|
| 57 |
+
alignItems: 'center',
|
| 58 |
+
justifyContent: 'space-between',
|
| 59 |
+
gap: '24px',
|
| 60 |
+
}}
|
| 61 |
+
>
|
| 62 |
+
{/* Logo */}
|
| 63 |
+
<div
|
| 64 |
+
style={{
|
| 65 |
+
fontFamily: 'var(--font-display)',
|
| 66 |
+
fontSize: '1rem',
|
| 67 |
+
color: '#F0F0FF',
|
| 68 |
+
letterSpacing: '0.08em',
|
| 69 |
+
cursor: 'pointer',
|
| 70 |
+
}}
|
| 71 |
+
onClick={() =>
|
| 72 |
+
window.scrollTo({
|
| 73 |
+
top: 0,
|
| 74 |
+
behavior: 'smooth',
|
| 75 |
+
})
|
| 76 |
+
}
|
| 77 |
+
>
|
| 78 |
+
SYSTEM
|
| 79 |
+
<span
|
| 80 |
+
style={{
|
| 81 |
+
color: '#E30913',
|
| 82 |
+
}}
|
| 83 |
+
>
|
| 84 |
+
FORGE
|
| 85 |
+
</span>
|
| 86 |
+
</div>
|
| 87 |
+
|
| 88 |
+
{/* Nav Links */}
|
| 89 |
+
<div
|
| 90 |
+
style={{
|
| 91 |
+
display: 'flex',
|
| 92 |
+
gap: '2rem',
|
| 93 |
+
alignItems: 'center',
|
| 94 |
+
}}
|
| 95 |
+
>
|
| 96 |
+
{navItems.map((item, index) => (
|
| 97 |
+
<motion.button
|
| 98 |
+
key={index}
|
| 99 |
+
whileHover={{
|
| 100 |
+
y: -2,
|
| 101 |
+
}}
|
| 102 |
+
onClick={() =>
|
| 103 |
+
scrollToSection(item.target)
|
| 104 |
+
}
|
| 105 |
+
style={{
|
| 106 |
+
background: 'transparent',
|
| 107 |
+
border: 'none',
|
| 108 |
+
cursor: 'pointer',
|
| 109 |
+
color: '#8888AA',
|
| 110 |
+
fontFamily: 'var(--font-mono)',
|
| 111 |
+
fontSize: '0.72rem',
|
| 112 |
+
letterSpacing: '0.12em',
|
| 113 |
+
}}
|
| 114 |
+
>
|
| 115 |
+
{item.label}
|
| 116 |
+
</motion.button>
|
| 117 |
+
))}
|
| 118 |
+
</div>
|
| 119 |
+
|
| 120 |
+
{/* Status */}
|
| 121 |
+
<div
|
| 122 |
+
style={{
|
| 123 |
+
padding: '8px 14px',
|
| 124 |
+
border:
|
| 125 |
+
'1px solid rgba(0,255,156,0.15)',
|
| 126 |
+
borderRadius: 6,
|
| 127 |
+
background:
|
| 128 |
+
'rgba(0,255,156,0.03)',
|
| 129 |
+
fontFamily: 'var(--font-mono)',
|
| 130 |
+
fontSize: '0.65rem',
|
| 131 |
+
color: '#00FF9C',
|
| 132 |
+
letterSpacing: '0.12em',
|
| 133 |
+
}}
|
| 134 |
+
>
|
| 135 |
+
AMD READY
|
| 136 |
+
</div>
|
| 137 |
+
</div>
|
| 138 |
+
</header>
|
| 139 |
+
);
|
| 140 |
+
}
|
frontend/components/workflow/BeforeAfterWorkflow.tsx
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import React from 'react';
|
| 4 |
+
import { motion } from 'framer-motion';
|
| 5 |
+
import FlowchartNode from './FlowchartNode';
|
| 6 |
+
import type { WorkflowTransformation } from '../../lib/types';
|
| 7 |
+
|
| 8 |
+
interface BeforeAfterWorkflowProps {
|
| 9 |
+
data: WorkflowTransformation;
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
function detectNodeType(step: string) {
|
| 13 |
+
const text = step.toLowerCase();
|
| 14 |
+
|
| 15 |
+
if (
|
| 16 |
+
text.includes('approve') ||
|
| 17 |
+
text.includes('approval')
|
| 18 |
+
) {
|
| 19 |
+
return 'approval';
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
if (
|
| 23 |
+
text.includes('decision') ||
|
| 24 |
+
text.includes('verify') ||
|
| 25 |
+
text.includes('check')
|
| 26 |
+
) {
|
| 27 |
+
return 'decision';
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
if (
|
| 31 |
+
text.includes('api') ||
|
| 32 |
+
text.includes('service')
|
| 33 |
+
) {
|
| 34 |
+
return 'api';
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
if (
|
| 38 |
+
text.includes('queue') ||
|
| 39 |
+
text.includes('kafka') ||
|
| 40 |
+
text.includes('async')
|
| 41 |
+
) {
|
| 42 |
+
return 'queue';
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
if (
|
| 46 |
+
text.includes('llm') ||
|
| 47 |
+
text.includes('ai') ||
|
| 48 |
+
text.includes('parser')
|
| 49 |
+
) {
|
| 50 |
+
return 'llm';
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
if (
|
| 54 |
+
text.includes('human') ||
|
| 55 |
+
text.includes('manual') ||
|
| 56 |
+
text.includes('review')
|
| 57 |
+
) {
|
| 58 |
+
return 'human_review';
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
if (
|
| 62 |
+
text.includes('email') ||
|
| 63 |
+
text.includes('notify') ||
|
| 64 |
+
text.includes('notification')
|
| 65 |
+
) {
|
| 66 |
+
return 'notification';
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
return 'task';
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
function mapWorkflowTypeToFlowchartType(type: string) {
|
| 73 |
+
switch (type) {
|
| 74 |
+
case 'input':
|
| 75 |
+
return 'input';
|
| 76 |
+
|
| 77 |
+
case 'task':
|
| 78 |
+
return 'task';
|
| 79 |
+
|
| 80 |
+
case 'decision':
|
| 81 |
+
return 'decision';
|
| 82 |
+
|
| 83 |
+
case 'automation':
|
| 84 |
+
return 'automation';
|
| 85 |
+
|
| 86 |
+
case 'approval':
|
| 87 |
+
return 'approval';
|
| 88 |
+
|
| 89 |
+
case 'output':
|
| 90 |
+
return 'output';
|
| 91 |
+
|
| 92 |
+
case 'api':
|
| 93 |
+
return 'api';
|
| 94 |
+
|
| 95 |
+
case 'queue':
|
| 96 |
+
return 'queue';
|
| 97 |
+
|
| 98 |
+
case 'llm':
|
| 99 |
+
return 'llm';
|
| 100 |
+
|
| 101 |
+
case 'human_review':
|
| 102 |
+
return 'human_review';
|
| 103 |
+
|
| 104 |
+
case 'notification':
|
| 105 |
+
return 'notification';
|
| 106 |
+
|
| 107 |
+
default:
|
| 108 |
+
return 'task';
|
| 109 |
+
}
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
export default function BeforeAfterWorkflow({
|
| 113 |
+
data,
|
| 114 |
+
}: BeforeAfterWorkflowProps) {
|
| 115 |
+
|
| 116 |
+
if (!data) {
|
| 117 |
+
return null;
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
return (
|
| 121 |
+
<section
|
| 122 |
+
id="workflow-engine"
|
| 123 |
+
style={{
|
| 124 |
+
position: 'relative',
|
| 125 |
+
zIndex: 10,
|
| 126 |
+
width: '100%',
|
| 127 |
+
padding: '6rem 2rem',
|
| 128 |
+
}}
|
| 129 |
+
>
|
| 130 |
+
<div
|
| 131 |
+
style={{
|
| 132 |
+
maxWidth: 1500,
|
| 133 |
+
margin: '0 auto',
|
| 134 |
+
}}
|
| 135 |
+
>
|
| 136 |
+
{/* Header */}
|
| 137 |
+
<motion.div
|
| 138 |
+
initial={{
|
| 139 |
+
opacity: 0,
|
| 140 |
+
y: 20,
|
| 141 |
+
}}
|
| 142 |
+
animate={{
|
| 143 |
+
opacity: 1,
|
| 144 |
+
y: 0,
|
| 145 |
+
}}
|
| 146 |
+
transition={{
|
| 147 |
+
duration: 0.5,
|
| 148 |
+
}}
|
| 149 |
+
style={{
|
| 150 |
+
textAlign: 'center',
|
| 151 |
+
marginBottom: '5rem',
|
| 152 |
+
}}
|
| 153 |
+
>
|
| 154 |
+
<div
|
| 155 |
+
style={{
|
| 156 |
+
fontFamily: 'var(--font-mono)',
|
| 157 |
+
fontSize: '0.75rem',
|
| 158 |
+
color: '#E30913',
|
| 159 |
+
letterSpacing: '0.28em',
|
| 160 |
+
marginBottom: '1rem',
|
| 161 |
+
}}
|
| 162 |
+
>
|
| 163 |
+
WORKFLOW REDESIGN ENGINE
|
| 164 |
+
</div>
|
| 165 |
+
|
| 166 |
+
<h2
|
| 167 |
+
style={{
|
| 168 |
+
fontFamily: 'var(--font-display)',
|
| 169 |
+
fontSize:
|
| 170 |
+
'clamp(2rem, 4vw, 4.5rem)',
|
| 171 |
+
color: '#F0F0FF',
|
| 172 |
+
marginBottom: '1rem',
|
| 173 |
+
}}
|
| 174 |
+
>
|
| 175 |
+
Before β After Transformation
|
| 176 |
+
</h2>
|
| 177 |
+
|
| 178 |
+
<p
|
| 179 |
+
style={{
|
| 180 |
+
maxWidth: 800,
|
| 181 |
+
margin: '0 auto',
|
| 182 |
+
color: '#8888AA',
|
| 183 |
+
fontSize: '1rem',
|
| 184 |
+
lineHeight: 1.8,
|
| 185 |
+
}}
|
| 186 |
+
>
|
| 187 |
+
Visualize how fragmented
|
| 188 |
+
manual operations transform
|
| 189 |
+
into production-grade,
|
| 190 |
+
AI-native operational systems.
|
| 191 |
+
</p>
|
| 192 |
+
</motion.div>
|
| 193 |
+
|
| 194 |
+
{/* Main Layout */}
|
| 195 |
+
<div
|
| 196 |
+
style={{
|
| 197 |
+
display: 'grid',
|
| 198 |
+
gridTemplateColumns:
|
| 199 |
+
'1fr 120px 1fr',
|
| 200 |
+
gap: '2rem',
|
| 201 |
+
alignItems: 'start',
|
| 202 |
+
}}
|
| 203 |
+
>
|
| 204 |
+
{/* BEFORE FLOW */}
|
| 205 |
+
<div>
|
| 206 |
+
<div
|
| 207 |
+
style={{
|
| 208 |
+
textAlign: 'center',
|
| 209 |
+
marginBottom: '2rem',
|
| 210 |
+
color: '#FFB800',
|
| 211 |
+
fontFamily: 'var(--font-mono)',
|
| 212 |
+
letterSpacing: '0.2em',
|
| 213 |
+
fontSize: '0.8rem',
|
| 214 |
+
}}
|
| 215 |
+
>
|
| 216 |
+
BEFORE β MANUAL WORKFLOW
|
| 217 |
+
</div>
|
| 218 |
+
|
| 219 |
+
{data.before.map((step, index) => (
|
| 220 |
+
<FlowchartNode
|
| 221 |
+
key={index}
|
| 222 |
+
title={step}
|
| 223 |
+
type={detectNodeType(step)}
|
| 224 |
+
isLast={index === data.before.length - 1}
|
| 225 |
+
/>
|
| 226 |
+
))}
|
| 227 |
+
</div>
|
| 228 |
+
|
| 229 |
+
{/* CENTER TRANSFORMATION */}
|
| 230 |
+
<div
|
| 231 |
+
style={{
|
| 232 |
+
display: 'flex',
|
| 233 |
+
justifyContent: 'center',
|
| 234 |
+
alignItems: 'center',
|
| 235 |
+
minHeight: 800,
|
| 236 |
+
}}
|
| 237 |
+
>
|
| 238 |
+
<motion.div
|
| 239 |
+
animate={{
|
| 240 |
+
x: [0, 10, 0],
|
| 241 |
+
}}
|
| 242 |
+
transition={{
|
| 243 |
+
repeat: Infinity,
|
| 244 |
+
duration: 2,
|
| 245 |
+
}}
|
| 246 |
+
style={{
|
| 247 |
+
fontSize: '4rem',
|
| 248 |
+
color: '#E30913',
|
| 249 |
+
fontWeight: 700,
|
| 250 |
+
}}
|
| 251 |
+
>
|
| 252 |
+
β
|
| 253 |
+
</motion.div>
|
| 254 |
+
</div>
|
| 255 |
+
|
| 256 |
+
{/* AFTER FLOW */}
|
| 257 |
+
<div>
|
| 258 |
+
<div
|
| 259 |
+
style={{
|
| 260 |
+
textAlign: 'center',
|
| 261 |
+
marginBottom: '2rem',
|
| 262 |
+
color: '#00FF9C',
|
| 263 |
+
fontFamily: 'var(--font-mono)',
|
| 264 |
+
letterSpacing: '0.2em',
|
| 265 |
+
fontSize: '0.8rem',
|
| 266 |
+
}}
|
| 267 |
+
>
|
| 268 |
+
AFTER β AI NATIVE SYSTEM
|
| 269 |
+
</div>
|
| 270 |
+
|
| 271 |
+
{data.after.map((step, index) => (
|
| 272 |
+
<FlowchartNode
|
| 273 |
+
key={index}
|
| 274 |
+
title={step}
|
| 275 |
+
type={detectNodeType(step)}
|
| 276 |
+
isLast={index === data.after.length - 1}
|
| 277 |
+
/>
|
| 278 |
+
))}
|
| 279 |
+
</div>
|
| 280 |
+
</div>
|
| 281 |
+
</div>
|
| 282 |
+
</section>
|
| 283 |
+
);
|
| 284 |
+
}
|
frontend/components/workflow/FlowchartNode.tsx
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import React from 'react';
|
| 4 |
+
import { motion } from 'framer-motion';
|
| 5 |
+
|
| 6 |
+
export type FlowchartNodeType =
|
| 7 |
+
| 'input'
|
| 8 |
+
| 'task'
|
| 9 |
+
| 'decision'
|
| 10 |
+
| 'automation'
|
| 11 |
+
| 'approval'
|
| 12 |
+
| 'output'
|
| 13 |
+
| 'api'
|
| 14 |
+
| 'queue'
|
| 15 |
+
| 'llm'
|
| 16 |
+
| 'human_review'
|
| 17 |
+
| 'notification';
|
| 18 |
+
|
| 19 |
+
interface FlowchartNodeProps {
|
| 20 |
+
title: string;
|
| 21 |
+
type: FlowchartNodeType;
|
| 22 |
+
subtitle?: string;
|
| 23 |
+
isLast?: boolean;
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
function getNodeAccent(
|
| 27 |
+
type: FlowchartNodeType
|
| 28 |
+
) {
|
| 29 |
+
switch (type) {
|
| 30 |
+
case 'input':
|
| 31 |
+
return '#06B6D4';
|
| 32 |
+
|
| 33 |
+
case 'automation':
|
| 34 |
+
return '#F97316';
|
| 35 |
+
|
| 36 |
+
case 'output':
|
| 37 |
+
return '#22C55E';
|
| 38 |
+
|
| 39 |
+
case 'decision':
|
| 40 |
+
return '#F59E0B';
|
| 41 |
+
|
| 42 |
+
case 'api':
|
| 43 |
+
return '#3B82F6';
|
| 44 |
+
|
| 45 |
+
case 'queue':
|
| 46 |
+
return '#8B5CF6';
|
| 47 |
+
|
| 48 |
+
case 'llm':
|
| 49 |
+
return '#EC4899';
|
| 50 |
+
|
| 51 |
+
case 'approval':
|
| 52 |
+
return '#22C55E';
|
| 53 |
+
|
| 54 |
+
case 'human_review':
|
| 55 |
+
return '#F97316';
|
| 56 |
+
|
| 57 |
+
case 'notification':
|
| 58 |
+
return '#06B6D4';
|
| 59 |
+
|
| 60 |
+
default:
|
| 61 |
+
return '#00D4FF';
|
| 62 |
+
}
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
function getNodeIcon(
|
| 66 |
+
type: FlowchartNodeType
|
| 67 |
+
) {
|
| 68 |
+
switch (type) {
|
| 69 |
+
case 'input':
|
| 70 |
+
return 'β‘';
|
| 71 |
+
|
| 72 |
+
case 'automation':
|
| 73 |
+
return 'β‘';
|
| 74 |
+
|
| 75 |
+
case 'output':
|
| 76 |
+
return 'β';
|
| 77 |
+
|
| 78 |
+
case 'decision':
|
| 79 |
+
return '?';
|
| 80 |
+
|
| 81 |
+
case 'api':
|
| 82 |
+
return 'β‘';
|
| 83 |
+
|
| 84 |
+
case 'queue':
|
| 85 |
+
return 'β';
|
| 86 |
+
|
| 87 |
+
case 'llm':
|
| 88 |
+
return 'π€';
|
| 89 |
+
|
| 90 |
+
case 'approval':
|
| 91 |
+
return 'β';
|
| 92 |
+
|
| 93 |
+
case 'human_review':
|
| 94 |
+
return 'π§';
|
| 95 |
+
|
| 96 |
+
case 'notification':
|
| 97 |
+
return 'π©';
|
| 98 |
+
|
| 99 |
+
default:
|
| 100 |
+
return 'β‘';
|
| 101 |
+
}
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
export default function FlowchartNode({
|
| 105 |
+
title,
|
| 106 |
+
type,
|
| 107 |
+
subtitle,
|
| 108 |
+
isLast = false,
|
| 109 |
+
}: FlowchartNodeProps) {
|
| 110 |
+
const accent = getNodeAccent(type);
|
| 111 |
+
const icon = getNodeIcon(type);
|
| 112 |
+
|
| 113 |
+
const isDecision =
|
| 114 |
+
type === 'decision';
|
| 115 |
+
|
| 116 |
+
return (
|
| 117 |
+
<motion.div
|
| 118 |
+
initial={{
|
| 119 |
+
opacity: 0,
|
| 120 |
+
y: 20,
|
| 121 |
+
}}
|
| 122 |
+
whileInView={{
|
| 123 |
+
opacity: 1,
|
| 124 |
+
y: 0,
|
| 125 |
+
}}
|
| 126 |
+
viewport={{
|
| 127 |
+
once: true,
|
| 128 |
+
}}
|
| 129 |
+
transition={{
|
| 130 |
+
duration: 0.45,
|
| 131 |
+
}}
|
| 132 |
+
style={{
|
| 133 |
+
display: 'flex',
|
| 134 |
+
flexDirection: 'column',
|
| 135 |
+
alignItems: 'center',
|
| 136 |
+
marginBottom: isLast ? 0 : 30,
|
| 137 |
+
}}
|
| 138 |
+
>
|
| 139 |
+
{/* NODE */}
|
| 140 |
+
<div
|
| 141 |
+
style={{
|
| 142 |
+
width: isDecision ? 220 : 360,
|
| 143 |
+
minHeight: isDecision
|
| 144 |
+
? 220
|
| 145 |
+
: 150,
|
| 146 |
+
|
| 147 |
+
display: 'flex',
|
| 148 |
+
alignItems: 'center',
|
| 149 |
+
justifyContent: 'center',
|
| 150 |
+
|
| 151 |
+
border: `1px solid ${accent}35`,
|
| 152 |
+
background: `${accent}08`,
|
| 153 |
+
backdropFilter: 'blur(14px)',
|
| 154 |
+
|
| 155 |
+
padding: isDecision
|
| 156 |
+
? '20px'
|
| 157 |
+
: '28px',
|
| 158 |
+
|
| 159 |
+
textAlign: 'center',
|
| 160 |
+
|
| 161 |
+
borderRadius: isDecision
|
| 162 |
+
? '28px'
|
| 163 |
+
: '22px',
|
| 164 |
+
|
| 165 |
+
transform: isDecision
|
| 166 |
+
? 'rotate(45deg)'
|
| 167 |
+
: 'none',
|
| 168 |
+
|
| 169 |
+
boxShadow: `0 0 0 1px ${accent}08`,
|
| 170 |
+
}}
|
| 171 |
+
>
|
| 172 |
+
<div
|
| 173 |
+
style={{
|
| 174 |
+
width: '100%',
|
| 175 |
+
maxWidth: isDecision
|
| 176 |
+
? '78%'
|
| 177 |
+
: '100%',
|
| 178 |
+
|
| 179 |
+
transform: isDecision
|
| 180 |
+
? 'rotate(-45deg)'
|
| 181 |
+
: 'none',
|
| 182 |
+
|
| 183 |
+
display: 'flex',
|
| 184 |
+
flexDirection: 'column',
|
| 185 |
+
alignItems: 'center',
|
| 186 |
+
justifyContent: 'center',
|
| 187 |
+
}}
|
| 188 |
+
>
|
| 189 |
+
{/* ICON ONLY */}
|
| 190 |
+
<div
|
| 191 |
+
style={{
|
| 192 |
+
color: accent,
|
| 193 |
+
fontSize: '24px',
|
| 194 |
+
fontWeight: 700,
|
| 195 |
+
marginBottom: '14px',
|
| 196 |
+
lineHeight: 1,
|
| 197 |
+
}}
|
| 198 |
+
>
|
| 199 |
+
{icon}
|
| 200 |
+
</div>
|
| 201 |
+
|
| 202 |
+
{/* TITLE ONLY */}
|
| 203 |
+
<div
|
| 204 |
+
style={{
|
| 205 |
+
color: '#F0F0FF',
|
| 206 |
+
fontSize: isDecision
|
| 207 |
+
? '15px'
|
| 208 |
+
: '16px',
|
| 209 |
+
fontWeight: 600,
|
| 210 |
+
lineHeight: 1.8,
|
| 211 |
+
letterSpacing: '0.01em',
|
| 212 |
+
wordBreak: 'break-word',
|
| 213 |
+
whiteSpace: 'normal',
|
| 214 |
+
}}
|
| 215 |
+
>
|
| 216 |
+
{title}
|
| 217 |
+
</div>
|
| 218 |
+
|
| 219 |
+
{/* Optional subtitle */}
|
| 220 |
+
{subtitle && (
|
| 221 |
+
<div
|
| 222 |
+
style={{
|
| 223 |
+
marginTop: '10px',
|
| 224 |
+
color: '#94A3B8',
|
| 225 |
+
fontSize: '12px',
|
| 226 |
+
lineHeight: 1.6,
|
| 227 |
+
}}
|
| 228 |
+
>
|
| 229 |
+
{subtitle}
|
| 230 |
+
</div>
|
| 231 |
+
)}
|
| 232 |
+
</div>
|
| 233 |
+
</div>
|
| 234 |
+
|
| 235 |
+
{/* CONNECTOR LINE */}
|
| 236 |
+
{!isLast && (
|
| 237 |
+
<div
|
| 238 |
+
style={{
|
| 239 |
+
width: '2px',
|
| 240 |
+
height: '38px',
|
| 241 |
+
marginTop: '14px',
|
| 242 |
+
background:
|
| 243 |
+
'rgba(255,255,255,0.08)',
|
| 244 |
+
}}
|
| 245 |
+
/>
|
| 246 |
+
)}
|
| 247 |
+
</motion.div>
|
| 248 |
+
);
|
| 249 |
+
}
|
frontend/components/workflow/WorkflowBuilder.tsx
ADDED
|
@@ -0,0 +1,550 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import React, { useState } from 'react';
|
| 4 |
+
import { EXAMPLE_WORKFLOWS } from '../../lib/exampleWorkflows';
|
| 5 |
+
import { WorkflowNodeType, WorkflowStep } from './WorkflowTypes';
|
| 6 |
+
|
| 7 |
+
interface WorkflowBuilderProps {
|
| 8 |
+
onGenerate: (workflowSteps: string[]) => void;
|
| 9 |
+
isRunning: boolean;
|
| 10 |
+
onWorkflowSelect: (workflowId: string | null) => void;
|
| 11 |
+
onWorkflowChange: () => void;
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
const STEP_TYPES = [
|
| 15 |
+
{ value: 'input', label: 'Input', icon: 'π₯' },
|
| 16 |
+
{ value: 'task', label: 'Task', icon: 'βοΈ' },
|
| 17 |
+
{ value: 'decision', label: 'Decision', icon: 'π' },
|
| 18 |
+
{ value: 'automation', label: 'Automation', icon: 'π€' },
|
| 19 |
+
{ value: 'approval', label: 'Approval', icon: 'β
' },
|
| 20 |
+
{ value: 'output', label: 'Output', icon: 'π€' },
|
| 21 |
+
{ value: 'api', label: 'API', icon: 'π' },
|
| 22 |
+
{ value: 'queue', label: 'Queue', icon: 'π¬' },
|
| 23 |
+
{ value: 'llm', label: 'LLM', icon: 'π§ ' },
|
| 24 |
+
{
|
| 25 |
+
value: 'human_review',
|
| 26 |
+
label: 'Human Review',
|
| 27 |
+
icon: 'π€',
|
| 28 |
+
},
|
| 29 |
+
{
|
| 30 |
+
value: 'notification',
|
| 31 |
+
label: 'Notification',
|
| 32 |
+
icon: 'π',
|
| 33 |
+
},
|
| 34 |
+
];
|
| 35 |
+
|
| 36 |
+
const DEFAULT_STEPS: WorkflowStep[] = [
|
| 37 |
+
{
|
| 38 |
+
id: '1',
|
| 39 |
+
type: 'input',
|
| 40 |
+
label: '',
|
| 41 |
+
},
|
| 42 |
+
{
|
| 43 |
+
id: '2',
|
| 44 |
+
type: 'task',
|
| 45 |
+
label: '',
|
| 46 |
+
},
|
| 47 |
+
{
|
| 48 |
+
id: '3',
|
| 49 |
+
type: 'decision',
|
| 50 |
+
label: '',
|
| 51 |
+
},
|
| 52 |
+
];
|
| 53 |
+
|
| 54 |
+
export default function WorkflowBuilder({
|
| 55 |
+
onGenerate,
|
| 56 |
+
isRunning,
|
| 57 |
+
onWorkflowSelect,
|
| 58 |
+
onWorkflowChange,
|
| 59 |
+
}: WorkflowBuilderProps) {
|
| 60 |
+
const [selectedExample, setSelectedExample] =
|
| 61 |
+
useState('');
|
| 62 |
+
|
| 63 |
+
const [workflowSteps, setWorkflowSteps] =
|
| 64 |
+
useState<WorkflowStep[]>(DEFAULT_STEPS);
|
| 65 |
+
|
| 66 |
+
const placeholders = [
|
| 67 |
+
'Step 1: What triggers your workflow?',
|
| 68 |
+
'Step 2: What happens next?',
|
| 69 |
+
'Step 3: Who approves or decides?',
|
| 70 |
+
];
|
| 71 |
+
|
| 72 |
+
const handleExampleChange = (
|
| 73 |
+
e: React.ChangeEvent<HTMLSelectElement>
|
| 74 |
+
) => {
|
| 75 |
+
const workflowId = e.target.value;
|
| 76 |
+
|
| 77 |
+
setSelectedExample(workflowId);
|
| 78 |
+
|
| 79 |
+
// reset old results
|
| 80 |
+
onWorkflowChange();
|
| 81 |
+
|
| 82 |
+
if (!workflowId) {
|
| 83 |
+
onWorkflowSelect(null);
|
| 84 |
+
setWorkflowSteps(DEFAULT_STEPS);
|
| 85 |
+
return;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
onWorkflowSelect(workflowId);
|
| 89 |
+
|
| 90 |
+
const selectedWorkflow =
|
| 91 |
+
EXAMPLE_WORKFLOWS.find(
|
| 92 |
+
(workflow) =>
|
| 93 |
+
workflow.id === workflowId
|
| 94 |
+
);
|
| 95 |
+
|
| 96 |
+
if (selectedWorkflow) {
|
| 97 |
+
setWorkflowSteps(
|
| 98 |
+
selectedWorkflow.before.map(
|
| 99 |
+
(step) => ({
|
| 100 |
+
id: step.id,
|
| 101 |
+
type: step.type,
|
| 102 |
+
label: step.label,
|
| 103 |
+
})
|
| 104 |
+
)
|
| 105 |
+
);
|
| 106 |
+
}
|
| 107 |
+
};
|
| 108 |
+
|
| 109 |
+
const clearExampleWorkflow = () => {
|
| 110 |
+
setSelectedExample('');
|
| 111 |
+
|
| 112 |
+
// reset old results
|
| 113 |
+
onWorkflowChange();
|
| 114 |
+
|
| 115 |
+
onWorkflowSelect(null);
|
| 116 |
+
setWorkflowSteps(DEFAULT_STEPS);
|
| 117 |
+
};
|
| 118 |
+
|
| 119 |
+
const updateStepLabel = (
|
| 120 |
+
id: string,
|
| 121 |
+
value: string
|
| 122 |
+
) => {
|
| 123 |
+
onWorkflowChange();
|
| 124 |
+
|
| 125 |
+
setWorkflowSteps((prev) =>
|
| 126 |
+
prev.map((step) =>
|
| 127 |
+
step.id === id
|
| 128 |
+
? {
|
| 129 |
+
...step,
|
| 130 |
+
label: value,
|
| 131 |
+
}
|
| 132 |
+
: step
|
| 133 |
+
)
|
| 134 |
+
);
|
| 135 |
+
};
|
| 136 |
+
|
| 137 |
+
const updateStepType = (
|
| 138 |
+
id: string,
|
| 139 |
+
type: WorkflowNodeType
|
| 140 |
+
) => {
|
| 141 |
+
onWorkflowChange();
|
| 142 |
+
|
| 143 |
+
setWorkflowSteps((prev) =>
|
| 144 |
+
prev.map((step) =>
|
| 145 |
+
step.id === id
|
| 146 |
+
? {
|
| 147 |
+
...step,
|
| 148 |
+
type,
|
| 149 |
+
}
|
| 150 |
+
: step
|
| 151 |
+
)
|
| 152 |
+
);
|
| 153 |
+
};
|
| 154 |
+
|
| 155 |
+
const addWorkflowStep = () => {
|
| 156 |
+
onWorkflowChange();
|
| 157 |
+
|
| 158 |
+
setWorkflowSteps((prev) => [
|
| 159 |
+
...prev,
|
| 160 |
+
{
|
| 161 |
+
id: Date.now().toString(),
|
| 162 |
+
type: 'task',
|
| 163 |
+
label: '',
|
| 164 |
+
},
|
| 165 |
+
]);
|
| 166 |
+
};
|
| 167 |
+
|
| 168 |
+
const removeStep = (id: string) => {
|
| 169 |
+
if (workflowSteps.length <= 1) return;
|
| 170 |
+
|
| 171 |
+
onWorkflowChange();
|
| 172 |
+
|
| 173 |
+
setWorkflowSteps((prev) =>
|
| 174 |
+
prev.filter(
|
| 175 |
+
(step) => step.id !== id
|
| 176 |
+
)
|
| 177 |
+
);
|
| 178 |
+
};
|
| 179 |
+
|
| 180 |
+
const handleGenerate = () => {
|
| 181 |
+
const cleanedSteps = workflowSteps
|
| 182 |
+
.map((step) => step.label.trim())
|
| 183 |
+
.filter(Boolean);
|
| 184 |
+
|
| 185 |
+
if (cleanedSteps.length === 0) {
|
| 186 |
+
alert(
|
| 187 |
+
'Please add at least one workflow step'
|
| 188 |
+
);
|
| 189 |
+
return;
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
onGenerate(cleanedSteps);
|
| 193 |
+
};
|
| 194 |
+
|
| 195 |
+
return (
|
| 196 |
+
<section
|
| 197 |
+
style={{
|
| 198 |
+
maxWidth: '1400px',
|
| 199 |
+
margin: '0 auto',
|
| 200 |
+
padding: '40px',
|
| 201 |
+
border:
|
| 202 |
+
'1px solid rgba(255,255,255,0.08)',
|
| 203 |
+
borderRadius: '24px',
|
| 204 |
+
background:
|
| 205 |
+
'rgba(5, 8, 22, 0.85)',
|
| 206 |
+
backdropFilter: 'blur(10px)',
|
| 207 |
+
}}
|
| 208 |
+
>
|
| 209 |
+
<div
|
| 210 |
+
style={{
|
| 211 |
+
fontSize: '56px',
|
| 212 |
+
fontWeight: 800,
|
| 213 |
+
marginBottom: '20px',
|
| 214 |
+
color: '#f8fafc',
|
| 215 |
+
}}
|
| 216 |
+
>
|
| 217 |
+
Map Your Current Workflow
|
| 218 |
+
</div>
|
| 219 |
+
|
| 220 |
+
<p
|
| 221 |
+
style={{
|
| 222 |
+
fontSize: '18px',
|
| 223 |
+
lineHeight: 1.8,
|
| 224 |
+
color: '#94a3b8',
|
| 225 |
+
marginBottom: '40px',
|
| 226 |
+
maxWidth: '1000px',
|
| 227 |
+
}}
|
| 228 |
+
>
|
| 229 |
+
Add your messy operational
|
| 230 |
+
process β approvals,
|
| 231 |
+
spreadsheets, manual
|
| 232 |
+
handoffs, broken workflows,
|
| 233 |
+
or disconnected systems.
|
| 234 |
+
SystemForge will redesign it
|
| 235 |
+
into a scalable
|
| 236 |
+
production-grade AI workflow.
|
| 237 |
+
</p>
|
| 238 |
+
|
| 239 |
+
{/* Example Workflow Dropdown */}
|
| 240 |
+
<div
|
| 241 |
+
style={{
|
| 242 |
+
marginBottom: '28px',
|
| 243 |
+
}}
|
| 244 |
+
>
|
| 245 |
+
<select
|
| 246 |
+
value={selectedExample}
|
| 247 |
+
onChange={
|
| 248 |
+
handleExampleChange
|
| 249 |
+
}
|
| 250 |
+
style={{
|
| 251 |
+
width: '100%',
|
| 252 |
+
padding: '20px',
|
| 253 |
+
borderRadius: '14px',
|
| 254 |
+
background: '#050816',
|
| 255 |
+
color: '#fff',
|
| 256 |
+
border:
|
| 257 |
+
'1px solid rgba(255,255,255,0.08)',
|
| 258 |
+
fontSize: '18px',
|
| 259 |
+
outline: 'none',
|
| 260 |
+
}}
|
| 261 |
+
>
|
| 262 |
+
<option value="">
|
| 263 |
+
Load Example Workflow
|
| 264 |
+
</option>
|
| 265 |
+
|
| 266 |
+
{EXAMPLE_WORKFLOWS.map(
|
| 267 |
+
(workflow) => (
|
| 268 |
+
<option
|
| 269 |
+
key={
|
| 270 |
+
workflow.id
|
| 271 |
+
}
|
| 272 |
+
value={
|
| 273 |
+
workflow.id
|
| 274 |
+
}
|
| 275 |
+
>
|
| 276 |
+
{
|
| 277 |
+
workflow.title
|
| 278 |
+
}{' '}
|
| 279 |
+
β{' '}
|
| 280 |
+
{
|
| 281 |
+
workflow.industry
|
| 282 |
+
}
|
| 283 |
+
</option>
|
| 284 |
+
)
|
| 285 |
+
)}
|
| 286 |
+
</select>
|
| 287 |
+
|
| 288 |
+
{selectedExample && (
|
| 289 |
+
<button
|
| 290 |
+
onClick={
|
| 291 |
+
clearExampleWorkflow
|
| 292 |
+
}
|
| 293 |
+
style={{
|
| 294 |
+
marginTop: '14px',
|
| 295 |
+
background:
|
| 296 |
+
'transparent',
|
| 297 |
+
border:
|
| 298 |
+
'1px solid #ef4444',
|
| 299 |
+
color:
|
| 300 |
+
'#ef4444',
|
| 301 |
+
padding:
|
| 302 |
+
'10px 18px',
|
| 303 |
+
borderRadius:
|
| 304 |
+
'10px',
|
| 305 |
+
cursor:
|
| 306 |
+
'pointer',
|
| 307 |
+
fontWeight: 600,
|
| 308 |
+
}}
|
| 309 |
+
>
|
| 310 |
+
Clear Example
|
| 311 |
+
Workflow
|
| 312 |
+
</button>
|
| 313 |
+
)}
|
| 314 |
+
</div>
|
| 315 |
+
|
| 316 |
+
{/* Workflow Steps */}
|
| 317 |
+
<div
|
| 318 |
+
style={{
|
| 319 |
+
display: 'flex',
|
| 320 |
+
flexDirection:
|
| 321 |
+
'column',
|
| 322 |
+
gap: '22px',
|
| 323 |
+
}}
|
| 324 |
+
>
|
| 325 |
+
{workflowSteps.map(
|
| 326 |
+
(step, index) => (
|
| 327 |
+
<div
|
| 328 |
+
key={step.id}
|
| 329 |
+
style={{
|
| 330 |
+
display:
|
| 331 |
+
'flex',
|
| 332 |
+
gap: '14px',
|
| 333 |
+
alignItems:
|
| 334 |
+
'center',
|
| 335 |
+
}}
|
| 336 |
+
>
|
| 337 |
+
{/* Step Number */}
|
| 338 |
+
<div
|
| 339 |
+
style={{
|
| 340 |
+
minWidth:
|
| 341 |
+
'60px',
|
| 342 |
+
fontSize:
|
| 343 |
+
'28px',
|
| 344 |
+
fontWeight: 700,
|
| 345 |
+
color:
|
| 346 |
+
'#00d4ff',
|
| 347 |
+
}}
|
| 348 |
+
>
|
| 349 |
+
{String(
|
| 350 |
+
index + 1
|
| 351 |
+
).padStart(
|
| 352 |
+
2,
|
| 353 |
+
'0'
|
| 354 |
+
)}
|
| 355 |
+
</div>
|
| 356 |
+
|
| 357 |
+
{/* Step Type */}
|
| 358 |
+
<select
|
| 359 |
+
value={
|
| 360 |
+
step.type
|
| 361 |
+
}
|
| 362 |
+
onChange={(
|
| 363 |
+
e
|
| 364 |
+
) =>
|
| 365 |
+
updateStepType(
|
| 366 |
+
step.id,
|
| 367 |
+
e
|
| 368 |
+
.target
|
| 369 |
+
.value as WorkflowNodeType
|
| 370 |
+
)
|
| 371 |
+
}
|
| 372 |
+
style={{
|
| 373 |
+
width:
|
| 374 |
+
'220px',
|
| 375 |
+
padding:
|
| 376 |
+
'16px',
|
| 377 |
+
borderRadius:
|
| 378 |
+
'12px',
|
| 379 |
+
background:
|
| 380 |
+
'#050816',
|
| 381 |
+
color:
|
| 382 |
+
'#fff',
|
| 383 |
+
border:
|
| 384 |
+
'1px solid rgba(255,255,255,0.08)',
|
| 385 |
+
fontSize:
|
| 386 |
+
'15px',
|
| 387 |
+
}}
|
| 388 |
+
>
|
| 389 |
+
{STEP_TYPES.map(
|
| 390 |
+
(
|
| 391 |
+
type
|
| 392 |
+
) => (
|
| 393 |
+
<option
|
| 394 |
+
key={
|
| 395 |
+
type.value
|
| 396 |
+
}
|
| 397 |
+
value={
|
| 398 |
+
type.value
|
| 399 |
+
}
|
| 400 |
+
>
|
| 401 |
+
{
|
| 402 |
+
type.icon
|
| 403 |
+
}{' '}
|
| 404 |
+
{
|
| 405 |
+
type.label
|
| 406 |
+
}
|
| 407 |
+
</option>
|
| 408 |
+
)
|
| 409 |
+
)}
|
| 410 |
+
</select>
|
| 411 |
+
|
| 412 |
+
{/* Step Input */}
|
| 413 |
+
<input
|
| 414 |
+
type="text"
|
| 415 |
+
value={
|
| 416 |
+
step.label
|
| 417 |
+
}
|
| 418 |
+
onChange={(
|
| 419 |
+
e
|
| 420 |
+
) =>
|
| 421 |
+
updateStepLabel(
|
| 422 |
+
step.id,
|
| 423 |
+
e
|
| 424 |
+
.target
|
| 425 |
+
.value
|
| 426 |
+
)
|
| 427 |
+
}
|
| 428 |
+
placeholder={
|
| 429 |
+
placeholders[
|
| 430 |
+
index
|
| 431 |
+
] ||
|
| 432 |
+
`Step ${index + 1}`
|
| 433 |
+
}
|
| 434 |
+
style={{
|
| 435 |
+
flex: 1,
|
| 436 |
+
padding:
|
| 437 |
+
'18px 20px',
|
| 438 |
+
borderRadius:
|
| 439 |
+
'12px',
|
| 440 |
+
background:
|
| 441 |
+
'#050816',
|
| 442 |
+
color:
|
| 443 |
+
'#fff',
|
| 444 |
+
border:
|
| 445 |
+
'1px solid rgba(255,255,255,0.08)',
|
| 446 |
+
fontSize:
|
| 447 |
+
'18px',
|
| 448 |
+
outline:
|
| 449 |
+
'none',
|
| 450 |
+
}}
|
| 451 |
+
/>
|
| 452 |
+
|
| 453 |
+
{/* Remove Button */}
|
| 454 |
+
<button
|
| 455 |
+
onClick={() =>
|
| 456 |
+
removeStep(
|
| 457 |
+
step.id
|
| 458 |
+
)
|
| 459 |
+
}
|
| 460 |
+
style={{
|
| 461 |
+
background:
|
| 462 |
+
'transparent',
|
| 463 |
+
border:
|
| 464 |
+
'1px solid #ef4444',
|
| 465 |
+
color:
|
| 466 |
+
'#ef4444',
|
| 467 |
+
padding:
|
| 468 |
+
'10px 18px',
|
| 469 |
+
borderRadius:
|
| 470 |
+
'10px',
|
| 471 |
+
cursor:
|
| 472 |
+
'pointer',
|
| 473 |
+
fontWeight: 700,
|
| 474 |
+
}}
|
| 475 |
+
>
|
| 476 |
+
Remove
|
| 477 |
+
</button>
|
| 478 |
+
</div>
|
| 479 |
+
)
|
| 480 |
+
)}
|
| 481 |
+
</div>
|
| 482 |
+
|
| 483 |
+
{/* Add Step */}
|
| 484 |
+
<div
|
| 485 |
+
style={{
|
| 486 |
+
display: 'flex',
|
| 487 |
+
justifyContent:
|
| 488 |
+
'center',
|
| 489 |
+
marginTop: '34px',
|
| 490 |
+
}}
|
| 491 |
+
>
|
| 492 |
+
<button
|
| 493 |
+
onClick={addWorkflowStep}
|
| 494 |
+
style={{
|
| 495 |
+
background:
|
| 496 |
+
'transparent',
|
| 497 |
+
border:
|
| 498 |
+
'1px solid #00d4ff',
|
| 499 |
+
color: '#00d4ff',
|
| 500 |
+
padding:
|
| 501 |
+
'18px 32px',
|
| 502 |
+
borderRadius:
|
| 503 |
+
'14px',
|
| 504 |
+
cursor:
|
| 505 |
+
'pointer',
|
| 506 |
+
fontWeight: 700,
|
| 507 |
+
fontSize: '16px',
|
| 508 |
+
}}
|
| 509 |
+
>
|
| 510 |
+
+ Add Workflow Step
|
| 511 |
+
</button>
|
| 512 |
+
</div>
|
| 513 |
+
|
| 514 |
+
{/* Generate Button */}
|
| 515 |
+
<button
|
| 516 |
+
onClick={handleGenerate}
|
| 517 |
+
disabled={isRunning}
|
| 518 |
+
style={{
|
| 519 |
+
background:
|
| 520 |
+
'linear-gradient(90deg, #dc2626, #ef4444)',
|
| 521 |
+
color: '#fff',
|
| 522 |
+
border: 'none',
|
| 523 |
+
padding:
|
| 524 |
+
'18px 32px',
|
| 525 |
+
borderRadius:
|
| 526 |
+
'14px',
|
| 527 |
+
fontSize: '16px',
|
| 528 |
+
fontWeight: 700,
|
| 529 |
+
cursor:
|
| 530 |
+
'pointer',
|
| 531 |
+
width: 'fit-content',
|
| 532 |
+
minWidth: '360px',
|
| 533 |
+
margin:
|
| 534 |
+
'42px auto 0',
|
| 535 |
+
display: 'block',
|
| 536 |
+
boxShadow:
|
| 537 |
+
'0 10px 30px rgba(239,68,68,0.20)',
|
| 538 |
+
opacity:
|
| 539 |
+
isRunning
|
| 540 |
+
? 0.7
|
| 541 |
+
: 1,
|
| 542 |
+
}}
|
| 543 |
+
>
|
| 544 |
+
{isRunning
|
| 545 |
+
? 'Generating...'
|
| 546 |
+
: 'β‘ Generate Production Architecture'}
|
| 547 |
+
</button>
|
| 548 |
+
</section>
|
| 549 |
+
);
|
| 550 |
+
}
|
frontend/components/workflow/WorkflowComparison.tsx
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import React from 'react';
|
| 4 |
+
import { motion } from 'framer-motion';
|
| 5 |
+
import type { SystemForgeResponse } from '../../lib/types';
|
| 6 |
+
|
| 7 |
+
interface WorkflowComparisonProps {
|
| 8 |
+
data: SystemForgeResponse;
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
interface ComparisonBlock {
|
| 12 |
+
title: string;
|
| 13 |
+
before: string;
|
| 14 |
+
after: string;
|
| 15 |
+
impact: string;
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
function buildComparisonBlocks(
|
| 19 |
+
before: string[],
|
| 20 |
+
after: string[]
|
| 21 |
+
): ComparisonBlock[] {
|
| 22 |
+
const maxLength = Math.max(
|
| 23 |
+
before.length,
|
| 24 |
+
after.length
|
| 25 |
+
);
|
| 26 |
+
|
| 27 |
+
const smartFallbacks = [
|
| 28 |
+
'New automation layer introduced',
|
| 29 |
+
'System-orchestrated validation added',
|
| 30 |
+
'Human escalation path introduced',
|
| 31 |
+
'Production monitoring layer added',
|
| 32 |
+
'Reliability safeguard introduced',
|
| 33 |
+
'Audit + observability layer created',
|
| 34 |
+
'Approval workflow optimization added',
|
| 35 |
+
'Async event handling introduced',
|
| 36 |
+
];
|
| 37 |
+
|
| 38 |
+
const impactOptions = [
|
| 39 |
+
'Reduced manual effort + faster execution',
|
| 40 |
+
'Improved reliability + production readiness',
|
| 41 |
+
'Lower operational bottlenecks + better scale',
|
| 42 |
+
'Higher audit visibility + safer approvals',
|
| 43 |
+
];
|
| 44 |
+
|
| 45 |
+
const blocks: ComparisonBlock[] = [];
|
| 46 |
+
|
| 47 |
+
for (let i = 0; i < maxLength; i++) {
|
| 48 |
+
blocks.push({
|
| 49 |
+
title: `Workflow Step ${String(
|
| 50 |
+
i + 1
|
| 51 |
+
).padStart(2, '0')}`,
|
| 52 |
+
|
| 53 |
+
before:
|
| 54 |
+
before[i] ||
|
| 55 |
+
smartFallbacks[
|
| 56 |
+
i % smartFallbacks.length
|
| 57 |
+
],
|
| 58 |
+
|
| 59 |
+
after:
|
| 60 |
+
after[i] ||
|
| 61 |
+
'System optimized this step',
|
| 62 |
+
|
| 63 |
+
impact:
|
| 64 |
+
impactOptions[
|
| 65 |
+
i % impactOptions.length
|
| 66 |
+
],
|
| 67 |
+
});
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
return blocks;
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
function ComparisonCard({
|
| 75 |
+
item,
|
| 76 |
+
index,
|
| 77 |
+
}: {
|
| 78 |
+
item: ComparisonBlock;
|
| 79 |
+
index: number;
|
| 80 |
+
}) {
|
| 81 |
+
return (
|
| 82 |
+
<motion.div
|
| 83 |
+
initial={{ opacity: 0, y: 20 }}
|
| 84 |
+
animate={{ opacity: 1, y: 0 }}
|
| 85 |
+
transition={{
|
| 86 |
+
delay: index * 0.08,
|
| 87 |
+
duration: 0.45,
|
| 88 |
+
}}
|
| 89 |
+
style={{
|
| 90 |
+
border: '1px solid rgba(255,255,255,0.06)',
|
| 91 |
+
background: 'rgba(255,255,255,0.02)',
|
| 92 |
+
borderRadius: 10,
|
| 93 |
+
padding: '1.8rem',
|
| 94 |
+
backdropFilter: 'blur(14px)',
|
| 95 |
+
}}
|
| 96 |
+
>
|
| 97 |
+
{/* Title */}
|
| 98 |
+
<div
|
| 99 |
+
style={{
|
| 100 |
+
fontFamily: 'var(--font-display)',
|
| 101 |
+
fontSize: '1rem',
|
| 102 |
+
color: '#F0F0FF',
|
| 103 |
+
marginBottom: '1.4rem',
|
| 104 |
+
letterSpacing: '0.05em',
|
| 105 |
+
}}
|
| 106 |
+
>
|
| 107 |
+
{item.title}
|
| 108 |
+
</div>
|
| 109 |
+
|
| 110 |
+
{/* Before */}
|
| 111 |
+
<div style={{ marginBottom: '1.2rem' }}>
|
| 112 |
+
<div
|
| 113 |
+
style={{
|
| 114 |
+
fontFamily: 'var(--font-mono)',
|
| 115 |
+
fontSize: '0.72rem',
|
| 116 |
+
color: '#FFB800',
|
| 117 |
+
letterSpacing: '0.18em',
|
| 118 |
+
marginBottom: '0.5rem',
|
| 119 |
+
}}
|
| 120 |
+
>
|
| 121 |
+
BEFORE
|
| 122 |
+
</div>
|
| 123 |
+
|
| 124 |
+
<div
|
| 125 |
+
style={{
|
| 126 |
+
color: '#8888AA',
|
| 127 |
+
lineHeight: 1.7,
|
| 128 |
+
fontSize: '0.95rem',
|
| 129 |
+
}}
|
| 130 |
+
>
|
| 131 |
+
{item.before}
|
| 132 |
+
</div>
|
| 133 |
+
</div>
|
| 134 |
+
|
| 135 |
+
{/* After */}
|
| 136 |
+
<div style={{ marginBottom: '1.2rem' }}>
|
| 137 |
+
<div
|
| 138 |
+
style={{
|
| 139 |
+
fontFamily: 'var(--font-mono)',
|
| 140 |
+
fontSize: '0.72rem',
|
| 141 |
+
color: '#00FF9C',
|
| 142 |
+
letterSpacing: '0.18em',
|
| 143 |
+
marginBottom: '0.5rem',
|
| 144 |
+
}}
|
| 145 |
+
>
|
| 146 |
+
AFTER
|
| 147 |
+
</div>
|
| 148 |
+
|
| 149 |
+
<div
|
| 150 |
+
style={{
|
| 151 |
+
color: '#F0F0FF',
|
| 152 |
+
lineHeight: 1.7,
|
| 153 |
+
fontSize: '0.95rem',
|
| 154 |
+
}}
|
| 155 |
+
>
|
| 156 |
+
{item.after}
|
| 157 |
+
</div>
|
| 158 |
+
</div>
|
| 159 |
+
|
| 160 |
+
{/* Impact */}
|
| 161 |
+
<div
|
| 162 |
+
style={{
|
| 163 |
+
borderTop: '1px solid rgba(255,255,255,0.05)',
|
| 164 |
+
paddingTop: '1rem',
|
| 165 |
+
}}
|
| 166 |
+
>
|
| 167 |
+
<div
|
| 168 |
+
style={{
|
| 169 |
+
fontFamily: 'var(--font-mono)',
|
| 170 |
+
fontSize: '0.7rem',
|
| 171 |
+
color: '#00D4FF',
|
| 172 |
+
letterSpacing: '0.18em',
|
| 173 |
+
marginBottom: '0.4rem',
|
| 174 |
+
}}
|
| 175 |
+
>
|
| 176 |
+
BUSINESS IMPACT
|
| 177 |
+
</div>
|
| 178 |
+
|
| 179 |
+
<div
|
| 180 |
+
style={{
|
| 181 |
+
color: '#00D4FF',
|
| 182 |
+
fontSize: '0.92rem',
|
| 183 |
+
lineHeight: 1.6,
|
| 184 |
+
}}
|
| 185 |
+
>
|
| 186 |
+
{item.impact}
|
| 187 |
+
</div>
|
| 188 |
+
</div>
|
| 189 |
+
</motion.div>
|
| 190 |
+
);
|
| 191 |
+
}
|
| 192 |
+
|
| 193 |
+
export default function WorkflowComparison({
|
| 194 |
+
data,
|
| 195 |
+
}: WorkflowComparisonProps) {
|
| 196 |
+
const comparisonBlocks = buildComparisonBlocks(
|
| 197 |
+
data.workflowTransformation.before,
|
| 198 |
+
data.workflowTransformation.after
|
| 199 |
+
);
|
| 200 |
+
|
| 201 |
+
return (
|
| 202 |
+
<section
|
| 203 |
+
style={{
|
| 204 |
+
position: 'relative',
|
| 205 |
+
zIndex: 10,
|
| 206 |
+
width: '100%',
|
| 207 |
+
padding: '4rem 2rem',
|
| 208 |
+
}}
|
| 209 |
+
>
|
| 210 |
+
<div
|
| 211 |
+
style={{
|
| 212 |
+
maxWidth: 1400,
|
| 213 |
+
margin: '0 auto',
|
| 214 |
+
}}
|
| 215 |
+
>
|
| 216 |
+
{/* Header */}
|
| 217 |
+
<motion.div
|
| 218 |
+
initial={{ opacity: 0, y: 18 }}
|
| 219 |
+
animate={{ opacity: 1, y: 0 }}
|
| 220 |
+
transition={{ duration: 0.5 }}
|
| 221 |
+
style={{
|
| 222 |
+
textAlign: 'center',
|
| 223 |
+
marginBottom: '3rem',
|
| 224 |
+
}}
|
| 225 |
+
>
|
| 226 |
+
<div
|
| 227 |
+
style={{
|
| 228 |
+
fontFamily: 'var(--font-mono)',
|
| 229 |
+
fontSize: '0.75rem',
|
| 230 |
+
color: '#00D4FF',
|
| 231 |
+
letterSpacing: '0.24em',
|
| 232 |
+
marginBottom: '0.8rem',
|
| 233 |
+
}}
|
| 234 |
+
>
|
| 235 |
+
WORKFLOW INTELLIGENCE LAYER
|
| 236 |
+
</div>
|
| 237 |
+
|
| 238 |
+
<h2
|
| 239 |
+
style={{
|
| 240 |
+
fontFamily: 'var(--font-display)',
|
| 241 |
+
fontSize: 'clamp(2rem, 4vw, 3.6rem)',
|
| 242 |
+
color: '#F0F0FF',
|
| 243 |
+
marginBottom: '1rem',
|
| 244 |
+
}}
|
| 245 |
+
>
|
| 246 |
+
Operational Redesign Breakdown
|
| 247 |
+
</h2>
|
| 248 |
+
|
| 249 |
+
<p
|
| 250 |
+
style={{
|
| 251 |
+
maxWidth: 760,
|
| 252 |
+
margin: '0 auto',
|
| 253 |
+
color: '#8888AA',
|
| 254 |
+
fontSize: '1rem',
|
| 255 |
+
lineHeight: 1.75,
|
| 256 |
+
}}
|
| 257 |
+
>
|
| 258 |
+
Every workflow redesign is broken into measurable
|
| 259 |
+
improvements. SystemForge explains what changed,
|
| 260 |
+
why it changed, and how the redesigned system
|
| 261 |
+
improves execution speed, scalability, and
|
| 262 |
+
operational reliability.
|
| 263 |
+
</p>
|
| 264 |
+
</motion.div>
|
| 265 |
+
|
| 266 |
+
{/* Grid */}
|
| 267 |
+
<div
|
| 268 |
+
style={{
|
| 269 |
+
display: 'grid',
|
| 270 |
+
gridTemplateColumns:
|
| 271 |
+
'repeat(auto-fit, minmax(320px, 1fr))',
|
| 272 |
+
gap: '1.5rem',
|
| 273 |
+
}}
|
| 274 |
+
>
|
| 275 |
+
{comparisonBlocks.map((item, index) => (
|
| 276 |
+
<ComparisonCard
|
| 277 |
+
key={index}
|
| 278 |
+
item={item}
|
| 279 |
+
index={index}
|
| 280 |
+
/>
|
| 281 |
+
))}
|
| 282 |
+
</div>
|
| 283 |
+
</div>
|
| 284 |
+
</section>
|
| 285 |
+
);
|
| 286 |
+
}
|
frontend/components/workflow/WorkflowNode.tsx
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import React from 'react';
|
| 4 |
+
import { motion } from 'framer-motion';
|
| 5 |
+
import type {
|
| 6 |
+
WorkflowStep,
|
| 7 |
+
WorkflowNodeType,
|
| 8 |
+
} from './WorkflowTypes';
|
| 9 |
+
|
| 10 |
+
interface Props {
|
| 11 |
+
step: WorkflowStep;
|
| 12 |
+
index: number;
|
| 13 |
+
updateStep: (
|
| 14 |
+
id: string,
|
| 15 |
+
field: 'label' | 'type',
|
| 16 |
+
value: string
|
| 17 |
+
) => void;
|
| 18 |
+
removeStep: (id: string) => void;
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
const NODE_OPTIONS: {
|
| 22 |
+
value: WorkflowNodeType;
|
| 23 |
+
label: string;
|
| 24 |
+
icon: string;
|
| 25 |
+
}[] = [
|
| 26 |
+
{ value: 'task', label: 'Task', icon: 'β‘' },
|
| 27 |
+
{ value: 'decision', label: 'Decision', icon: 'β' },
|
| 28 |
+
{ value: 'approval', label: 'Approval', icon: 'β' },
|
| 29 |
+
{ value: 'api', label: 'API', icon: 'β‘' },
|
| 30 |
+
{ value: 'queue', label: 'Queue', icon: 'β' },
|
| 31 |
+
{ value: 'llm', label: 'LLM', icon: 'π€' },
|
| 32 |
+
{
|
| 33 |
+
value: 'human_review',
|
| 34 |
+
label: 'Human Review',
|
| 35 |
+
icon: 'π§',
|
| 36 |
+
},
|
| 37 |
+
{
|
| 38 |
+
value: 'notification',
|
| 39 |
+
label: 'Notification',
|
| 40 |
+
icon: 'π©',
|
| 41 |
+
},
|
| 42 |
+
];
|
| 43 |
+
|
| 44 |
+
function getAccent(type: WorkflowNodeType) {
|
| 45 |
+
switch (type) {
|
| 46 |
+
case 'decision':
|
| 47 |
+
return '#F59E0B';
|
| 48 |
+
case 'approval':
|
| 49 |
+
return '#22C55E';
|
| 50 |
+
case 'api':
|
| 51 |
+
return '#3B82F6';
|
| 52 |
+
case 'queue':
|
| 53 |
+
return '#8B5CF6';
|
| 54 |
+
case 'llm':
|
| 55 |
+
return '#EC4899';
|
| 56 |
+
case 'human_review':
|
| 57 |
+
return '#F97316';
|
| 58 |
+
case 'notification':
|
| 59 |
+
return '#06B6D4';
|
| 60 |
+
default:
|
| 61 |
+
return '#00D4FF';
|
| 62 |
+
}
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
export default function WorkflowNode({
|
| 66 |
+
step,
|
| 67 |
+
index,
|
| 68 |
+
updateStep,
|
| 69 |
+
removeStep,
|
| 70 |
+
}: Props) {
|
| 71 |
+
const accent = getAccent(step.type);
|
| 72 |
+
|
| 73 |
+
const isDecision =
|
| 74 |
+
step.type === 'decision';
|
| 75 |
+
|
| 76 |
+
return (
|
| 77 |
+
<motion.div
|
| 78 |
+
initial={{
|
| 79 |
+
opacity: 0,
|
| 80 |
+
y: 20,
|
| 81 |
+
}}
|
| 82 |
+
animate={{
|
| 83 |
+
opacity: 1,
|
| 84 |
+
y: 0,
|
| 85 |
+
}}
|
| 86 |
+
style={{
|
| 87 |
+
marginBottom: '20px',
|
| 88 |
+
}}
|
| 89 |
+
>
|
| 90 |
+
<div
|
| 91 |
+
style={{
|
| 92 |
+
display: 'flex',
|
| 93 |
+
alignItems: 'center',
|
| 94 |
+
gap: '16px',
|
| 95 |
+
}}
|
| 96 |
+
>
|
| 97 |
+
{/* Node Shape */}
|
| 98 |
+
<div
|
| 99 |
+
style={{
|
| 100 |
+
width: 58,
|
| 101 |
+
height: 58,
|
| 102 |
+
minWidth: 58,
|
| 103 |
+
display: 'flex',
|
| 104 |
+
alignItems: 'center',
|
| 105 |
+
justifyContent: 'center',
|
| 106 |
+
border: `1px solid ${accent}30`,
|
| 107 |
+
background: `${accent}08`,
|
| 108 |
+
color: accent,
|
| 109 |
+
fontSize: '18px',
|
| 110 |
+
fontWeight: 700,
|
| 111 |
+
transform: isDecision
|
| 112 |
+
? 'rotate(45deg)'
|
| 113 |
+
: 'none',
|
| 114 |
+
borderRadius: isDecision
|
| 115 |
+
? '8px'
|
| 116 |
+
: '14px',
|
| 117 |
+
}}
|
| 118 |
+
>
|
| 119 |
+
<span
|
| 120 |
+
style={{
|
| 121 |
+
transform: isDecision
|
| 122 |
+
? 'rotate(-45deg)'
|
| 123 |
+
: 'none',
|
| 124 |
+
}}
|
| 125 |
+
>
|
| 126 |
+
{isDecision
|
| 127 |
+
? '?'
|
| 128 |
+
: String(index + 1).padStart(
|
| 129 |
+
2,
|
| 130 |
+
'0'
|
| 131 |
+
)}
|
| 132 |
+
</span>
|
| 133 |
+
</div>
|
| 134 |
+
|
| 135 |
+
{/* Main Card */}
|
| 136 |
+
<div
|
| 137 |
+
style={{
|
| 138 |
+
flex: 1,
|
| 139 |
+
display: 'flex',
|
| 140 |
+
alignItems: 'center',
|
| 141 |
+
gap: '14px',
|
| 142 |
+
border:
|
| 143 |
+
'1px solid rgba(255,255,255,0.08)',
|
| 144 |
+
background:
|
| 145 |
+
'rgba(255,255,255,0.02)',
|
| 146 |
+
borderRadius: '18px',
|
| 147 |
+
padding: '18px 20px',
|
| 148 |
+
backdropFilter: 'blur(8px)',
|
| 149 |
+
}}
|
| 150 |
+
>
|
| 151 |
+
{/* Type */}
|
| 152 |
+
<select
|
| 153 |
+
value={step.type}
|
| 154 |
+
onChange={(e) =>
|
| 155 |
+
updateStep(
|
| 156 |
+
step.id,
|
| 157 |
+
'type',
|
| 158 |
+
e.target.value
|
| 159 |
+
)
|
| 160 |
+
}
|
| 161 |
+
style={{
|
| 162 |
+
border: 'none',
|
| 163 |
+
background: 'transparent',
|
| 164 |
+
color: accent,
|
| 165 |
+
fontWeight: 600,
|
| 166 |
+
fontSize: '14px',
|
| 167 |
+
outline: 'none',
|
| 168 |
+
minWidth: 120,
|
| 169 |
+
}}
|
| 170 |
+
>
|
| 171 |
+
{NODE_OPTIONS.map((item) => (
|
| 172 |
+
<option
|
| 173 |
+
key={item.value}
|
| 174 |
+
value={item.value}
|
| 175 |
+
style={{
|
| 176 |
+
background: '#111827',
|
| 177 |
+
color: '#ffffff',
|
| 178 |
+
}}
|
| 179 |
+
>
|
| 180 |
+
{item.icon} {item.label}
|
| 181 |
+
</option>
|
| 182 |
+
))}
|
| 183 |
+
</select>
|
| 184 |
+
|
| 185 |
+
{/* Input */}
|
| 186 |
+
<input
|
| 187 |
+
value={step.label}
|
| 188 |
+
onChange={(e) =>
|
| 189 |
+
updateStep(
|
| 190 |
+
step.id,
|
| 191 |
+
'label',
|
| 192 |
+
e.target.value
|
| 193 |
+
)
|
| 194 |
+
}
|
| 195 |
+
placeholder="Describe workflow step..."
|
| 196 |
+
style={{
|
| 197 |
+
flex: 1,
|
| 198 |
+
border: 'none',
|
| 199 |
+
background: 'transparent',
|
| 200 |
+
color: '#F0F0FF',
|
| 201 |
+
fontSize: '16px',
|
| 202 |
+
outline: 'none',
|
| 203 |
+
}}
|
| 204 |
+
/>
|
| 205 |
+
|
| 206 |
+
{/* Remove */}
|
| 207 |
+
<button
|
| 208 |
+
onClick={() =>
|
| 209 |
+
removeStep(step.id)
|
| 210 |
+
}
|
| 211 |
+
style={{
|
| 212 |
+
border: 'none',
|
| 213 |
+
background: 'transparent',
|
| 214 |
+
color: '#EF4444',
|
| 215 |
+
fontWeight: 600,
|
| 216 |
+
cursor: 'pointer',
|
| 217 |
+
fontSize: '14px',
|
| 218 |
+
}}
|
| 219 |
+
>
|
| 220 |
+
Remove
|
| 221 |
+
</button>
|
| 222 |
+
</div>
|
| 223 |
+
</div>
|
| 224 |
+
</motion.div>
|
| 225 |
+
);
|
| 226 |
+
}
|
frontend/components/workflow/WorkflowTypes.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export type WorkflowNodeType =
|
| 2 |
+
| 'input'
|
| 3 |
+
| 'task'
|
| 4 |
+
| 'decision'
|
| 5 |
+
| 'automation'
|
| 6 |
+
| 'approval'
|
| 7 |
+
| 'output'
|
| 8 |
+
| 'api'
|
| 9 |
+
| 'queue'
|
| 10 |
+
| 'llm'
|
| 11 |
+
| 'human_review'
|
| 12 |
+
| 'notification';
|
| 13 |
+
|
| 14 |
+
export interface WorkflowStep {
|
| 15 |
+
id: string;
|
| 16 |
+
type: WorkflowNodeType;
|
| 17 |
+
label: string;
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
export interface ExampleWorkflow {
|
| 21 |
+
id: string;
|
| 22 |
+
title: string;
|
| 23 |
+
industry: string;
|
| 24 |
+
before: WorkflowStep[];
|
| 25 |
+
after: WorkflowStep[];
|
| 26 |
+
estimatedReduction: string;
|
| 27 |
+
}
|
frontend/legacy/app.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
from src.workflows.crew import run_systemforge
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def execute_systemforge(project_idea: str):
|
| 6 |
+
if not project_idea.strip():
|
| 7 |
+
return (
|
| 8 |
+
"Please enter a project idea.",
|
| 9 |
+
"No review generated.",
|
| 10 |
+
"No refined architecture generated."
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
try:
|
| 14 |
+
final_result = run_systemforge(project_idea)
|
| 15 |
+
|
| 16 |
+
architect_output = f"""
|
| 17 |
+
# Architect Agent Output
|
| 18 |
+
|
| 19 |
+
Project Idea: {project_idea}
|
| 20 |
+
|
| 21 |
+
The Architect Agent generated the initial production architecture plan.
|
| 22 |
+
"""
|
| 23 |
+
|
| 24 |
+
critic_output = """
|
| 25 |
+
# Critic Agent Output (Senior SRE Persona)
|
| 26 |
+
|
| 27 |
+
The Critic Agent reviewed the architecture for:
|
| 28 |
+
- scalability risks
|
| 29 |
+
- observability gaps
|
| 30 |
+
- fault tolerance
|
| 31 |
+
- security concerns
|
| 32 |
+
- production reliability
|
| 33 |
+
"""
|
| 34 |
+
|
| 35 |
+
refiner_output = f"""
|
| 36 |
+
# Refiner Agent Output
|
| 37 |
+
|
| 38 |
+
{final_result}
|
| 39 |
+
"""
|
| 40 |
+
|
| 41 |
+
return architect_output, critic_output, refiner_output
|
| 42 |
+
|
| 43 |
+
except Exception as e:
|
| 44 |
+
return (
|
| 45 |
+
"Architect Agent execution failed.",
|
| 46 |
+
"Critic Agent execution failed.",
|
| 47 |
+
f"System Error: {str(e)}"
|
| 48 |
+
)
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
with gr.Blocks(title="SystemForge AI") as demo:
|
| 52 |
+
gr.Markdown("""
|
| 53 |
+
# SystemForge AI
|
| 54 |
+
### Autonomous Multi-Agent Architecture Engine
|
| 55 |
+
|
| 56 |
+
Architect β Critic β Refiner
|
| 57 |
+
|
| 58 |
+
Describe your startup or product idea and let the agents generate a production-grade system design.
|
| 59 |
+
""")
|
| 60 |
+
|
| 61 |
+
project_input = gr.Textbox(
|
| 62 |
+
label="Describe Your Project Idea",
|
| 63 |
+
placeholder="Example: Build a scalable fintech SaaS platform for SMB lending",
|
| 64 |
+
lines=4,
|
| 65 |
+
)
|
| 66 |
+
|
| 67 |
+
run_button = gr.Button("Run SystemForge")
|
| 68 |
+
|
| 69 |
+
architect_box = gr.Markdown(label="Architect Output")
|
| 70 |
+
critic_box = gr.Markdown(label="Critic Output")
|
| 71 |
+
refiner_box = gr.Markdown(label="Refiner Output")
|
| 72 |
+
|
| 73 |
+
run_button.click(
|
| 74 |
+
fn=execute_systemforge,
|
| 75 |
+
inputs=[project_input],
|
| 76 |
+
outputs=[architect_box, critic_box, refiner_box],
|
| 77 |
+
)
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
if __name__ == "__main__":
|
| 81 |
+
demo.launch()
|
frontend/lib/api.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import type { SystemForgeResponse } from "./types";
|
| 2 |
+
|
| 3 |
+
export async function generateWorkflowRedesign(
|
| 4 |
+
workflowSteps: string[]
|
| 5 |
+
): Promise<SystemForgeResponse> {
|
| 6 |
+
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
| 7 |
+
|
| 8 |
+
if (!API_URL) {
|
| 9 |
+
throw new Error(
|
| 10 |
+
"NEXT_PUBLIC_API_URL is missing in .env"
|
| 11 |
+
);
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
const response = await fetch(
|
| 15 |
+
`${API_URL}/run-systemforge`,
|
| 16 |
+
{
|
| 17 |
+
method: "POST",
|
| 18 |
+
headers: {
|
| 19 |
+
"Content-Type": "application/json",
|
| 20 |
+
},
|
| 21 |
+
body: JSON.stringify({
|
| 22 |
+
workflow: workflowSteps,
|
| 23 |
+
}),
|
| 24 |
+
}
|
| 25 |
+
);
|
| 26 |
+
|
| 27 |
+
const data = await response.json();
|
| 28 |
+
|
| 29 |
+
if (!response.ok) {
|
| 30 |
+
throw new Error(
|
| 31 |
+
data.detail ||
|
| 32 |
+
data.error ||
|
| 33 |
+
"Failed to generate architecture"
|
| 34 |
+
);
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
return data;
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
export async function downloadArchitectureReport(
|
| 42 |
+
workflowSteps: string[]
|
| 43 |
+
): Promise<void> {
|
| 44 |
+
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
| 45 |
+
|
| 46 |
+
if (!API_URL) {
|
| 47 |
+
throw new Error(
|
| 48 |
+
"NEXT_PUBLIC_API_URL is missing in .env"
|
| 49 |
+
);
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
const response = await fetch(
|
| 53 |
+
`${API_URL}/download-report`,
|
| 54 |
+
{
|
| 55 |
+
method: "POST",
|
| 56 |
+
headers: {
|
| 57 |
+
"Content-Type": "application/json",
|
| 58 |
+
},
|
| 59 |
+
body: JSON.stringify({
|
| 60 |
+
workflow: workflowSteps,
|
| 61 |
+
}),
|
| 62 |
+
}
|
| 63 |
+
);
|
| 64 |
+
|
| 65 |
+
if (!response.ok) {
|
| 66 |
+
let errorMessage =
|
| 67 |
+
"Failed to download report";
|
| 68 |
+
|
| 69 |
+
try {
|
| 70 |
+
const errorData =
|
| 71 |
+
await response.json();
|
| 72 |
+
|
| 73 |
+
errorMessage =
|
| 74 |
+
errorData.detail ||
|
| 75 |
+
errorData.error ||
|
| 76 |
+
errorMessage;
|
| 77 |
+
} catch {
|
| 78 |
+
// fallback if response is not JSON
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
throw new Error(errorMessage);
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
const blob = await response.blob();
|
| 85 |
+
const url =
|
| 86 |
+
window.URL.createObjectURL(blob);
|
| 87 |
+
|
| 88 |
+
const link =
|
| 89 |
+
document.createElement("a");
|
| 90 |
+
|
| 91 |
+
link.href = url;
|
| 92 |
+
link.download =
|
| 93 |
+
"SystemForge_Architecture_Report.pdf";
|
| 94 |
+
|
| 95 |
+
document.body.appendChild(link);
|
| 96 |
+
link.click();
|
| 97 |
+
link.remove();
|
| 98 |
+
|
| 99 |
+
window.URL.revokeObjectURL(url);
|
| 100 |
+
}
|
frontend/lib/exampleWorkflows.ts
ADDED
|
@@ -0,0 +1,482 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { ExampleWorkflow } from '../components/workflow/WorkflowTypes';
|
| 2 |
+
|
| 3 |
+
export const EXAMPLE_WORKFLOWS: ExampleWorkflow[] = [
|
| 4 |
+
{
|
| 5 |
+
id: 'insurance-claims',
|
| 6 |
+
title: 'Insurance Claims Processing',
|
| 7 |
+
industry: 'Insurance Operations',
|
| 8 |
+
|
| 9 |
+
before: [
|
| 10 |
+
{
|
| 11 |
+
id: 'b1',
|
| 12 |
+
type: 'input',
|
| 13 |
+
label: 'Customer emails a claim',
|
| 14 |
+
},
|
| 15 |
+
{
|
| 16 |
+
id: 'b2',
|
| 17 |
+
type: 'task',
|
| 18 |
+
label: 'Agent opens email manually in Outlook',
|
| 19 |
+
},
|
| 20 |
+
{
|
| 21 |
+
id: 'b3',
|
| 22 |
+
type: 'task',
|
| 23 |
+
label: 'Reads claim details manually',
|
| 24 |
+
},
|
| 25 |
+
{
|
| 26 |
+
id: 'b4',
|
| 27 |
+
type: 'task',
|
| 28 |
+
label: 'Logs into Policy Portal to search policy',
|
| 29 |
+
},
|
| 30 |
+
{
|
| 31 |
+
id: 'b5',
|
| 32 |
+
type: 'decision',
|
| 33 |
+
label: 'Checks claim history in Claims DB',
|
| 34 |
+
},
|
| 35 |
+
{
|
| 36 |
+
id: 'b6',
|
| 37 |
+
type: 'task',
|
| 38 |
+
label: 'Cross-verifies coverage limits manually',
|
| 39 |
+
},
|
| 40 |
+
{
|
| 41 |
+
id: 'b7',
|
| 42 |
+
type: 'task',
|
| 43 |
+
label: 'Creates summary in spreadsheet',
|
| 44 |
+
},
|
| 45 |
+
{
|
| 46 |
+
id: 'b8',
|
| 47 |
+
type: 'task',
|
| 48 |
+
label: 'Emails supervisor for approval',
|
| 49 |
+
},
|
| 50 |
+
{
|
| 51 |
+
id: 'b9',
|
| 52 |
+
type: 'decision',
|
| 53 |
+
label: 'Supervisor approves or rejects',
|
| 54 |
+
},
|
| 55 |
+
{
|
| 56 |
+
id: 'b10',
|
| 57 |
+
type: 'output',
|
| 58 |
+
label: 'Drafts approval or rejection email',
|
| 59 |
+
},
|
| 60 |
+
],
|
| 61 |
+
|
| 62 |
+
after: [
|
| 63 |
+
{
|
| 64 |
+
id: 'a1',
|
| 65 |
+
type: 'automation',
|
| 66 |
+
label: 'Claim intake service captures email automatically',
|
| 67 |
+
},
|
| 68 |
+
{
|
| 69 |
+
id: 'a2',
|
| 70 |
+
type: 'automation',
|
| 71 |
+
label: 'Document parser extracts claim details + policy info',
|
| 72 |
+
},
|
| 73 |
+
{
|
| 74 |
+
id: 'a3',
|
| 75 |
+
type: 'decision',
|
| 76 |
+
label: 'Claims DB + Policy validation check',
|
| 77 |
+
},
|
| 78 |
+
{
|
| 79 |
+
id: 'a4',
|
| 80 |
+
type: 'automation',
|
| 81 |
+
label: 'Coverage validation engine verifies limits',
|
| 82 |
+
},
|
| 83 |
+
{
|
| 84 |
+
id: 'a5',
|
| 85 |
+
type: 'approval',
|
| 86 |
+
label: 'Auto decision: approve / reject / escalate',
|
| 87 |
+
},
|
| 88 |
+
{
|
| 89 |
+
id: 'a6',
|
| 90 |
+
type: 'output',
|
| 91 |
+
label: 'LLM drafts customer response + CRM updated',
|
| 92 |
+
},
|
| 93 |
+
],
|
| 94 |
+
|
| 95 |
+
estimatedReduction: '45β60 min β 10β15 min',
|
| 96 |
+
},
|
| 97 |
+
|
| 98 |
+
{
|
| 99 |
+
id: 'recruitment-screening',
|
| 100 |
+
title: 'Recruitment Candidate Screening',
|
| 101 |
+
industry: 'Hiring Operations',
|
| 102 |
+
|
| 103 |
+
before: [
|
| 104 |
+
{
|
| 105 |
+
id: 'b1',
|
| 106 |
+
type: 'input',
|
| 107 |
+
label: 'Resumes arrive from LinkedIn',
|
| 108 |
+
},
|
| 109 |
+
{
|
| 110 |
+
id: 'b2',
|
| 111 |
+
type: 'task',
|
| 112 |
+
label: 'HR downloads resumes manually',
|
| 113 |
+
},
|
| 114 |
+
{
|
| 115 |
+
id: 'b3',
|
| 116 |
+
type: 'task',
|
| 117 |
+
label: 'Reviews candidate profile manually',
|
| 118 |
+
},
|
| 119 |
+
{
|
| 120 |
+
id: 'b4',
|
| 121 |
+
type: 'decision',
|
| 122 |
+
label: 'Checks job fit in spreadsheet',
|
| 123 |
+
},
|
| 124 |
+
{
|
| 125 |
+
id: 'b5',
|
| 126 |
+
type: 'task',
|
| 127 |
+
label: 'Compares against JD manually',
|
| 128 |
+
},
|
| 129 |
+
{
|
| 130 |
+
id: 'b6',
|
| 131 |
+
type: 'task',
|
| 132 |
+
label: 'Sends shortlist to hiring manager',
|
| 133 |
+
},
|
| 134 |
+
{
|
| 135 |
+
id: 'b7',
|
| 136 |
+
type: 'decision',
|
| 137 |
+
label: 'Manager approves interview round',
|
| 138 |
+
},
|
| 139 |
+
{
|
| 140 |
+
id: 'b8',
|
| 141 |
+
type: 'output',
|
| 142 |
+
label: 'Recruiter sends candidate response',
|
| 143 |
+
},
|
| 144 |
+
],
|
| 145 |
+
|
| 146 |
+
after: [
|
| 147 |
+
{
|
| 148 |
+
id: 'a1',
|
| 149 |
+
type: 'automation',
|
| 150 |
+
label: 'Resume intake API ingests candidate profiles',
|
| 151 |
+
},
|
| 152 |
+
{
|
| 153 |
+
id: 'a2',
|
| 154 |
+
type: 'automation',
|
| 155 |
+
label: 'Resume parser extracts skills + experience',
|
| 156 |
+
},
|
| 157 |
+
{
|
| 158 |
+
id: 'a3',
|
| 159 |
+
type: 'automation',
|
| 160 |
+
label: 'Skill matching engine scores JD fit',
|
| 161 |
+
},
|
| 162 |
+
{
|
| 163 |
+
id: 'a4',
|
| 164 |
+
type: 'approval',
|
| 165 |
+
label: 'Auto shortlist / reject / escalate',
|
| 166 |
+
},
|
| 167 |
+
{
|
| 168 |
+
id: 'a5',
|
| 169 |
+
type: 'output',
|
| 170 |
+
label: 'LLM drafts recruiter email + ATS updated',
|
| 171 |
+
},
|
| 172 |
+
],
|
| 173 |
+
|
| 174 |
+
estimatedReduction: '35β50 min β 5β8 min',
|
| 175 |
+
},
|
| 176 |
+
|
| 177 |
+
{
|
| 178 |
+
id: 'accounts-payable',
|
| 179 |
+
title: 'Accounts Payable Invoice Processing',
|
| 180 |
+
industry: 'Finance Operations',
|
| 181 |
+
|
| 182 |
+
before: [
|
| 183 |
+
{
|
| 184 |
+
id: 'b1',
|
| 185 |
+
type: 'input',
|
| 186 |
+
label: 'Vendor emails invoice PDF',
|
| 187 |
+
},
|
| 188 |
+
{
|
| 189 |
+
id: 'b2',
|
| 190 |
+
type: 'task',
|
| 191 |
+
label: 'Finance downloads invoice manually',
|
| 192 |
+
},
|
| 193 |
+
{
|
| 194 |
+
id: 'b3',
|
| 195 |
+
type: 'task',
|
| 196 |
+
label: 'Reads invoice details manually',
|
| 197 |
+
},
|
| 198 |
+
{
|
| 199 |
+
id: 'b4',
|
| 200 |
+
type: 'decision',
|
| 201 |
+
label: 'Checks PO and vendor details',
|
| 202 |
+
},
|
| 203 |
+
{
|
| 204 |
+
id: 'b5',
|
| 205 |
+
type: 'task',
|
| 206 |
+
label: 'Validates GST + payment terms',
|
| 207 |
+
},
|
| 208 |
+
{
|
| 209 |
+
id: 'b6',
|
| 210 |
+
type: 'task',
|
| 211 |
+
label: 'Creates approval note in spreadsheet',
|
| 212 |
+
},
|
| 213 |
+
{
|
| 214 |
+
id: 'b7',
|
| 215 |
+
type: 'approval',
|
| 216 |
+
label: 'Manager approves payment',
|
| 217 |
+
},
|
| 218 |
+
{
|
| 219 |
+
id: 'b8',
|
| 220 |
+
type: 'output',
|
| 221 |
+
label: 'Finance updates ERP manually',
|
| 222 |
+
},
|
| 223 |
+
],
|
| 224 |
+
|
| 225 |
+
after: [
|
| 226 |
+
{
|
| 227 |
+
id: 'a1',
|
| 228 |
+
type: 'automation',
|
| 229 |
+
label: 'Invoice parser extracts PDF invoice data',
|
| 230 |
+
},
|
| 231 |
+
{
|
| 232 |
+
id: 'a2',
|
| 233 |
+
type: 'decision',
|
| 234 |
+
label: 'PO + Vendor validation layer checks match',
|
| 235 |
+
},
|
| 236 |
+
{
|
| 237 |
+
id: 'a3',
|
| 238 |
+
type: 'automation',
|
| 239 |
+
label: 'Tax validation engine verifies GST rules',
|
| 240 |
+
},
|
| 241 |
+
{
|
| 242 |
+
id: 'a4',
|
| 243 |
+
type: 'approval',
|
| 244 |
+
label: 'Auto approval routing based on invoice value',
|
| 245 |
+
},
|
| 246 |
+
{
|
| 247 |
+
id: 'a5',
|
| 248 |
+
type: 'output',
|
| 249 |
+
label: 'ERP updated + payment workflow triggered',
|
| 250 |
+
},
|
| 251 |
+
],
|
| 252 |
+
|
| 253 |
+
estimatedReduction: '40β55 min β 7β10 min',
|
| 254 |
+
},
|
| 255 |
+
|
| 256 |
+
{
|
| 257 |
+
id: 'vendor-onboarding',
|
| 258 |
+
title: 'Vendor Onboarding',
|
| 259 |
+
industry: 'Procurement Operations',
|
| 260 |
+
|
| 261 |
+
before: [
|
| 262 |
+
{
|
| 263 |
+
id: 'b1',
|
| 264 |
+
type: 'input',
|
| 265 |
+
label: 'Vendor submits onboarding form',
|
| 266 |
+
},
|
| 267 |
+
{
|
| 268 |
+
id: 'b2',
|
| 269 |
+
type: 'task',
|
| 270 |
+
label: 'Ops team manually validates GST',
|
| 271 |
+
},
|
| 272 |
+
{
|
| 273 |
+
id: 'b3',
|
| 274 |
+
type: 'task',
|
| 275 |
+
label: 'Bank account verification done manually',
|
| 276 |
+
},
|
| 277 |
+
{
|
| 278 |
+
id: 'b4',
|
| 279 |
+
type: 'task',
|
| 280 |
+
label: 'PAN and compliance docs reviewed',
|
| 281 |
+
},
|
| 282 |
+
{
|
| 283 |
+
id: 'b5',
|
| 284 |
+
type: 'decision',
|
| 285 |
+
label: 'Checks duplicate vendor risk',
|
| 286 |
+
},
|
| 287 |
+
{
|
| 288 |
+
id: 'b6',
|
| 289 |
+
type: 'approval',
|
| 290 |
+
label: 'Procurement manager approves vendor',
|
| 291 |
+
},
|
| 292 |
+
{
|
| 293 |
+
id: 'b7',
|
| 294 |
+
type: 'output',
|
| 295 |
+
label: 'Vendor added to ERP manually',
|
| 296 |
+
},
|
| 297 |
+
],
|
| 298 |
+
|
| 299 |
+
after: [
|
| 300 |
+
{
|
| 301 |
+
id: 'a1',
|
| 302 |
+
type: 'automation',
|
| 303 |
+
label: 'Vendor onboarding API receives form data',
|
| 304 |
+
},
|
| 305 |
+
{
|
| 306 |
+
id: 'a2',
|
| 307 |
+
type: 'automation',
|
| 308 |
+
label: 'GST + PAN verification services validate documents',
|
| 309 |
+
},
|
| 310 |
+
{
|
| 311 |
+
id: 'a3',
|
| 312 |
+
type: 'automation',
|
| 313 |
+
label: 'Bank verification service validates account',
|
| 314 |
+
},
|
| 315 |
+
{
|
| 316 |
+
id: 'a4',
|
| 317 |
+
type: 'decision',
|
| 318 |
+
label: 'Duplicate vendor risk engine check',
|
| 319 |
+
},
|
| 320 |
+
{
|
| 321 |
+
id: 'a5',
|
| 322 |
+
type: 'approval',
|
| 323 |
+
label: 'Approval workflow triggered automatically',
|
| 324 |
+
},
|
| 325 |
+
{
|
| 326 |
+
id: 'a6',
|
| 327 |
+
type: 'output',
|
| 328 |
+
label: 'Vendor master created in ERP',
|
| 329 |
+
},
|
| 330 |
+
],
|
| 331 |
+
|
| 332 |
+
estimatedReduction: '60β90 min β 10β15 min',
|
| 333 |
+
},
|
| 334 |
+
|
| 335 |
+
{
|
| 336 |
+
id: 'expense-reimbursement',
|
| 337 |
+
title: 'Employee Expense Reimbursement',
|
| 338 |
+
industry: 'Internal Finance',
|
| 339 |
+
|
| 340 |
+
before: [
|
| 341 |
+
{
|
| 342 |
+
id: 'b1',
|
| 343 |
+
type: 'input',
|
| 344 |
+
label: 'Employee emails reimbursement request',
|
| 345 |
+
},
|
| 346 |
+
{
|
| 347 |
+
id: 'b2',
|
| 348 |
+
type: 'task',
|
| 349 |
+
label: 'Finance opens receipts manually',
|
| 350 |
+
},
|
| 351 |
+
{
|
| 352 |
+
id: 'b3',
|
| 353 |
+
type: 'task',
|
| 354 |
+
label: 'Reads expense details line by line',
|
| 355 |
+
},
|
| 356 |
+
{
|
| 357 |
+
id: 'b4',
|
| 358 |
+
type: 'decision',
|
| 359 |
+
label: 'Checks policy compliance manually',
|
| 360 |
+
},
|
| 361 |
+
{
|
| 362 |
+
id: 'b5',
|
| 363 |
+
type: 'task',
|
| 364 |
+
label: 'Creates approval note',
|
| 365 |
+
},
|
| 366 |
+
{
|
| 367 |
+
id: 'b6',
|
| 368 |
+
type: 'approval',
|
| 369 |
+
label: 'Manager approves reimbursement',
|
| 370 |
+
},
|
| 371 |
+
{
|
| 372 |
+
id: 'b7',
|
| 373 |
+
type: 'output',
|
| 374 |
+
label: 'Finance updates payroll manually',
|
| 375 |
+
},
|
| 376 |
+
],
|
| 377 |
+
|
| 378 |
+
after: [
|
| 379 |
+
{
|
| 380 |
+
id: 'a1',
|
| 381 |
+
type: 'automation',
|
| 382 |
+
label: 'Receipt parser extracts expense details',
|
| 383 |
+
},
|
| 384 |
+
{
|
| 385 |
+
id: 'a2',
|
| 386 |
+
type: 'automation',
|
| 387 |
+
label: 'Policy compliance engine validates expenses',
|
| 388 |
+
},
|
| 389 |
+
{
|
| 390 |
+
id: 'a3',
|
| 391 |
+
type: 'decision',
|
| 392 |
+
label: 'Fraud + duplicate claim detection',
|
| 393 |
+
},
|
| 394 |
+
{
|
| 395 |
+
id: 'a4',
|
| 396 |
+
type: 'approval',
|
| 397 |
+
label: 'Smart approval routing to manager',
|
| 398 |
+
},
|
| 399 |
+
{
|
| 400 |
+
id: 'a5',
|
| 401 |
+
type: 'output',
|
| 402 |
+
label: 'Payroll updated + employee notified',
|
| 403 |
+
},
|
| 404 |
+
],
|
| 405 |
+
|
| 406 |
+
estimatedReduction: '30β45 min β 5β7 min',
|
| 407 |
+
},
|
| 408 |
+
|
| 409 |
+
{
|
| 410 |
+
id: 'customer-support',
|
| 411 |
+
title: 'Customer Support Escalation',
|
| 412 |
+
industry: 'Support Operations',
|
| 413 |
+
|
| 414 |
+
before: [
|
| 415 |
+
{
|
| 416 |
+
id: 'b1',
|
| 417 |
+
type: 'input',
|
| 418 |
+
label: 'Customer raises support ticket',
|
| 419 |
+
},
|
| 420 |
+
{
|
| 421 |
+
id: 'b2',
|
| 422 |
+
type: 'task',
|
| 423 |
+
label: 'Agent reads ticket manually',
|
| 424 |
+
},
|
| 425 |
+
{
|
| 426 |
+
id: 'b3',
|
| 427 |
+
type: 'task',
|
| 428 |
+
label: 'Checks CRM for customer history',
|
| 429 |
+
},
|
| 430 |
+
{
|
| 431 |
+
id: 'b4',
|
| 432 |
+
type: 'decision',
|
| 433 |
+
label: 'Determines issue severity manually',
|
| 434 |
+
},
|
| 435 |
+
{
|
| 436 |
+
id: 'b5',
|
| 437 |
+
type: 'task',
|
| 438 |
+
label: 'Routes ticket to correct team',
|
| 439 |
+
},
|
| 440 |
+
{
|
| 441 |
+
id: 'b6',
|
| 442 |
+
type: 'approval',
|
| 443 |
+
label: 'Supervisor handles critical escalation',
|
| 444 |
+
},
|
| 445 |
+
{
|
| 446 |
+
id: 'b7',
|
| 447 |
+
type: 'output',
|
| 448 |
+
label: 'Customer receives final update',
|
| 449 |
+
},
|
| 450 |
+
],
|
| 451 |
+
|
| 452 |
+
after: [
|
| 453 |
+
{
|
| 454 |
+
id: 'a1',
|
| 455 |
+
type: 'automation',
|
| 456 |
+
label: 'Ticket parser classifies issue automatically',
|
| 457 |
+
},
|
| 458 |
+
{
|
| 459 |
+
id: 'a2',
|
| 460 |
+
type: 'automation',
|
| 461 |
+
label: 'CRM lookup service fetches customer history',
|
| 462 |
+
},
|
| 463 |
+
{
|
| 464 |
+
id: 'a3',
|
| 465 |
+
type: 'decision',
|
| 466 |
+
label: 'Severity + SLA priority engine',
|
| 467 |
+
},
|
| 468 |
+
{
|
| 469 |
+
id: 'a4',
|
| 470 |
+
type: 'approval',
|
| 471 |
+
label: 'Critical cases escalated to human lead',
|
| 472 |
+
},
|
| 473 |
+
{
|
| 474 |
+
id: 'a5',
|
| 475 |
+
type: 'output',
|
| 476 |
+
label: 'Auto response + routing + CRM update',
|
| 477 |
+
},
|
| 478 |
+
],
|
| 479 |
+
|
| 480 |
+
estimatedReduction: '25β40 min β 3β5 min',
|
| 481 |
+
},
|
| 482 |
+
];
|
frontend/lib/types.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export interface WorkflowTransformation {
|
| 2 |
+
before: string[];
|
| 3 |
+
after: string[];
|
| 4 |
+
}
|
| 5 |
+
|
| 6 |
+
export type AgentStatus = 'idle' | 'thinking' | 'complete' | 'error';
|
| 7 |
+
|
| 8 |
+
export interface AgentOutput {
|
| 9 |
+
agent: 'architect' | 'critic' | 'refiner';
|
| 10 |
+
status: AgentStatus;
|
| 11 |
+
content: string;
|
| 12 |
+
duration?: number;
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
export interface AgentDecision {
|
| 16 |
+
title: string;
|
| 17 |
+
subtitle: string;
|
| 18 |
+
decisions: string[];
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
export interface ArchitectureLayer {
|
| 22 |
+
title: string;
|
| 23 |
+
description: string;
|
| 24 |
+
items: string[];
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
export interface FinalMetrics {
|
| 28 |
+
deploymentReadiness: string;
|
| 29 |
+
automationPotential: string;
|
| 30 |
+
architectureConfidence: string;
|
| 31 |
+
riskScore: string;
|
| 32 |
+
estimatedMonthlyInfraCost: string;
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
export interface SystemForgeResponse {
|
| 36 |
+
workflowTransformation: WorkflowTransformation;
|
| 37 |
+
|
| 38 |
+
architect: AgentDecision;
|
| 39 |
+
critic: AgentDecision;
|
| 40 |
+
refiner: AgentDecision;
|
| 41 |
+
|
| 42 |
+
architectureLayers: ArchitectureLayer[];
|
| 43 |
+
|
| 44 |
+
finalMetrics: FinalMetrics;
|
| 45 |
+
|
| 46 |
+
executiveSummary: AgentDecision;
|
| 47 |
+
}
|
frontend/next-env.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/// <reference types="next" />
|
| 2 |
+
/// <reference types="next/image-types/global" />
|
| 3 |
+
import "./.next/dev/types/routes.d.ts";
|
| 4 |
+
|
| 5 |
+
// NOTE: This file should not be edited
|
| 6 |
+
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
frontend/package-lock.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
frontend/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "systemforge-ai-frontend",
|
| 3 |
+
"version": "1.0.0",
|
| 4 |
+
"private": true,
|
| 5 |
+
"scripts": {
|
| 6 |
+
"dev": "next dev",
|
| 7 |
+
"build": "next build",
|
| 8 |
+
"start": "next start",
|
| 9 |
+
"lint": "next lint"
|
| 10 |
+
},
|
| 11 |
+
"dependencies": {
|
| 12 |
+
"@ant-design/icons": "^5.3.7",
|
| 13 |
+
"@react-three/drei": "^9.122.0",
|
| 14 |
+
"@react-three/fiber": "^8.18.0",
|
| 15 |
+
"antd": "^5.19.0",
|
| 16 |
+
"clsx": "^2.1.1",
|
| 17 |
+
"framer-motion": "^11.18.2",
|
| 18 |
+
"leva": "^0.9.35",
|
| 19 |
+
"next": "^16.2.4",
|
| 20 |
+
"react": "^18.3.1",
|
| 21 |
+
"react-dom": "^18.3.1",
|
| 22 |
+
"three": "^0.166.1"
|
| 23 |
+
},
|
| 24 |
+
"devDependencies": {
|
| 25 |
+
"@types/node": "^20",
|
| 26 |
+
"@types/react": "^18",
|
| 27 |
+
"@types/react-dom": "^18",
|
| 28 |
+
"@types/three": "^0.166.0",
|
| 29 |
+
"eslint": "^10.3.0",
|
| 30 |
+
"eslint-config-next": "^16.2.4",
|
| 31 |
+
"typescript": "^5"
|
| 32 |
+
}
|
| 33 |
+
}
|
frontend/styles/globals.css
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;600;700;900&family=JetBrains+Mono:wght@300;400;500;700&family=Rajdhani:wght@300;400;500;600;700&display=swap');
|
| 2 |
+
|
| 3 |
+
:root {
|
| 4 |
+
--amd-red: #E30913;
|
| 5 |
+
--bg-void: #020204;
|
| 6 |
+
--text-primary: #F0F0FF;
|
| 7 |
+
--text-secondary: #8888AA;
|
| 8 |
+
|
| 9 |
+
--accent-cyan: #00D4FF;
|
| 10 |
+
--accent-gold: #FFB800;
|
| 11 |
+
--accent-green: #00FF9C;
|
| 12 |
+
|
| 13 |
+
--font-display: 'Orbitron', monospace;
|
| 14 |
+
--font-body: 'Rajdhani', sans-serif;
|
| 15 |
+
--font-mono: 'JetBrains Mono', monospace;
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
/* RESET */
|
| 19 |
+
|
| 20 |
+
*,
|
| 21 |
+
*::before,
|
| 22 |
+
*::after {
|
| 23 |
+
box-sizing: border-box;
|
| 24 |
+
margin: 0;
|
| 25 |
+
padding: 0;
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
html {
|
| 29 |
+
scroll-behavior: smooth;
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
body {
|
| 33 |
+
font-family: var(--font-body);
|
| 34 |
+
background: var(--bg-void);
|
| 35 |
+
color: var(--text-primary);
|
| 36 |
+
min-height: 100vh;
|
| 37 |
+
overflow-x: hidden;
|
| 38 |
+
-webkit-font-smoothing: antialiased;
|
| 39 |
+
-moz-osx-font-smoothing: grayscale;
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
/* SCROLLBAR */
|
| 43 |
+
|
| 44 |
+
::-webkit-scrollbar {
|
| 45 |
+
width: 4px;
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
::-webkit-scrollbar-track {
|
| 49 |
+
background: #07070F;
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
::-webkit-scrollbar-thumb {
|
| 53 |
+
background: var(--amd-red);
|
| 54 |
+
border-radius: 2px;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
/* PREMIUM BACKGROUND */
|
| 58 |
+
|
| 59 |
+
.cyber-background {
|
| 60 |
+
position: fixed;
|
| 61 |
+
inset: 0;
|
| 62 |
+
z-index: 0;
|
| 63 |
+
pointer-events: none;
|
| 64 |
+
overflow: hidden;
|
| 65 |
+
background:
|
| 66 |
+
radial-gradient(circle at 20% 20%, rgba(227, 9, 19, 0.12), transparent 35%),
|
| 67 |
+
radial-gradient(circle at 80% 30%, rgba(0, 212, 255, 0.10), transparent 35%),
|
| 68 |
+
radial-gradient(circle at 50% 80%, rgba(0, 255, 153, 0.08), transparent 40%),
|
| 69 |
+
#03040a;
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
.grid-overlay {
|
| 73 |
+
position: absolute;
|
| 74 |
+
inset: 0;
|
| 75 |
+
background-image:
|
| 76 |
+
linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px),
|
| 77 |
+
linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
|
| 78 |
+
background-size: 80px 80px;
|
| 79 |
+
opacity: 0.35;
|
| 80 |
+
animation: gridMove 20s linear infinite;
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
.glow {
|
| 84 |
+
position: absolute;
|
| 85 |
+
width: 500px;
|
| 86 |
+
height: 500px;
|
| 87 |
+
border-radius: 50%;
|
| 88 |
+
filter: blur(120px);
|
| 89 |
+
opacity: 0.45;
|
| 90 |
+
animation: pulseGlow 8s ease-in-out infinite;
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
.glow-red {
|
| 94 |
+
background: rgba(227, 9, 19, 0.35);
|
| 95 |
+
top: 10%;
|
| 96 |
+
left: 10%;
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
.glow-blue {
|
| 100 |
+
background: rgba(0, 212, 255, 0.28);
|
| 101 |
+
top: 20%;
|
| 102 |
+
right: 10%;
|
| 103 |
+
animation-delay: 2s;
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
.glow-green {
|
| 107 |
+
background: rgba(0, 255, 153, 0.20);
|
| 108 |
+
bottom: 5%;
|
| 109 |
+
left: 35%;
|
| 110 |
+
animation-delay: 4s;
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
.scan-line {
|
| 114 |
+
position: absolute;
|
| 115 |
+
left: 0;
|
| 116 |
+
width: 100%;
|
| 117 |
+
height: 2px;
|
| 118 |
+
background: linear-gradient(90deg,
|
| 119 |
+
transparent,
|
| 120 |
+
rgba(255, 255, 255, 0.25),
|
| 121 |
+
transparent);
|
| 122 |
+
animation: scanMove 6s linear infinite;
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
/* ANIMATIONS */
|
| 126 |
+
|
| 127 |
+
@keyframes gridMove {
|
| 128 |
+
from {
|
| 129 |
+
transform: translateY(0px);
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
to {
|
| 133 |
+
transform: translateY(80px);
|
| 134 |
+
}
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
+
@keyframes pulseGlow {
|
| 138 |
+
|
| 139 |
+
0%,
|
| 140 |
+
100% {
|
| 141 |
+
transform: scale(1);
|
| 142 |
+
opacity: 0.35;
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
50% {
|
| 146 |
+
transform: scale(1.12);
|
| 147 |
+
opacity: 0.55;
|
| 148 |
+
}
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
@keyframes scanMove {
|
| 152 |
+
from {
|
| 153 |
+
top: -10%;
|
| 154 |
+
}
|
| 155 |
+
|
| 156 |
+
to {
|
| 157 |
+
top: 110%;
|
| 158 |
+
}
|
| 159 |
+
}
|
frontend/tsconfig.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"compilerOptions": {
|
| 3 |
+
"target": "ES2017",
|
| 4 |
+
"lib": [
|
| 5 |
+
"dom",
|
| 6 |
+
"dom.iterable",
|
| 7 |
+
"esnext"
|
| 8 |
+
],
|
| 9 |
+
"allowJs": true,
|
| 10 |
+
"skipLibCheck": true,
|
| 11 |
+
"strict": false,
|
| 12 |
+
"noEmit": true,
|
| 13 |
+
"incremental": true,
|
| 14 |
+
"module": "esnext",
|
| 15 |
+
"esModuleInterop": true,
|
| 16 |
+
"moduleResolution": "bundler",
|
| 17 |
+
"resolveJsonModule": true,
|
| 18 |
+
"isolatedModules": true,
|
| 19 |
+
"jsx": "react-jsx",
|
| 20 |
+
"plugins": [
|
| 21 |
+
{
|
| 22 |
+
"name": "next"
|
| 23 |
+
}
|
| 24 |
+
]
|
| 25 |
+
},
|
| 26 |
+
"include": [
|
| 27 |
+
"next-env.d.ts",
|
| 28 |
+
".next/types/**/*.ts",
|
| 29 |
+
".next/dev/types/**/*.ts",
|
| 30 |
+
"**/*.mts",
|
| 31 |
+
"**/*.ts",
|
| 32 |
+
"**/*.tsx"
|
| 33 |
+
],
|
| 34 |
+
"exclude": [
|
| 35 |
+
"node_modules"
|
| 36 |
+
]
|
| 37 |
+
}
|
frontend/tsconfig.tsbuildinfo
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
requirements.txt
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
crewai
|
| 2 |
+
pydantic
|
| 3 |
+
python-dotenv
|
| 4 |
+
fastapi
|
| 5 |
+
uvicorn
|
| 6 |
+
langchain
|
| 7 |
+
langchain-openai
|
| 8 |
+
langchain-groq
|
| 9 |
+
gradio
|
| 10 |
+
reportlab
|
| 11 |
+
setuptools<70
|
| 12 |
+
wheel
|
src/agents/architect.py
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from src.tools.llm import get_llm
|
| 2 |
+
from src.tools.json_parser import safe_json_parse
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def architect_agent(workflow_steps, bottlenecks=None):
|
| 6 |
+
"""
|
| 7 |
+
Systems Architect Agent
|
| 8 |
+
"""
|
| 9 |
+
|
| 10 |
+
llm = get_llm()
|
| 11 |
+
|
| 12 |
+
prompt = f"""
|
| 13 |
+
You are the SYSTEMS ARCHITECT Agent inside SystemForge.
|
| 14 |
+
|
| 15 |
+
You are a Principal Staff Engineer responsible for designing
|
| 16 |
+
production-grade enterprise AI systems.
|
| 17 |
+
|
| 18 |
+
Your job is NOT to give generic automation advice.
|
| 19 |
+
|
| 20 |
+
Your job is to design:
|
| 21 |
+
REAL production architecture.
|
| 22 |
+
|
| 23 |
+
You think like:
|
| 24 |
+
- Principal Engineer
|
| 25 |
+
- Staff Systems Architect
|
| 26 |
+
- Platform Engineer
|
| 27 |
+
- Distributed Systems Designer
|
| 28 |
+
|
| 29 |
+
You optimize for:
|
| 30 |
+
- scale
|
| 31 |
+
- reliability
|
| 32 |
+
- fault tolerance
|
| 33 |
+
- human override
|
| 34 |
+
- observability
|
| 35 |
+
- retry safety
|
| 36 |
+
- compliance
|
| 37 |
+
- auditability
|
| 38 |
+
- operational excellence
|
| 39 |
+
|
| 40 |
+
You do NOT write like a consultant.
|
| 41 |
+
|
| 42 |
+
You write like an engineer designing
|
| 43 |
+
real production systems.
|
| 44 |
+
|
| 45 |
+
-----------------------------------
|
| 46 |
+
INPUT WORKFLOW
|
| 47 |
+
-----------------------------------
|
| 48 |
+
|
| 49 |
+
{workflow_steps}
|
| 50 |
+
|
| 51 |
+
-----------------------------------
|
| 52 |
+
KNOWN BOTTLENECKS
|
| 53 |
+
-----------------------------------
|
| 54 |
+
|
| 55 |
+
{bottlenecks}
|
| 56 |
+
|
| 57 |
+
-----------------------------------
|
| 58 |
+
YOUR TASK
|
| 59 |
+
-----------------------------------
|
| 60 |
+
|
| 61 |
+
Redesign this workflow into an AI-native production system.
|
| 62 |
+
|
| 63 |
+
You MUST include:
|
| 64 |
+
|
| 65 |
+
1. Async event-driven workflow where needed
|
| 66 |
+
2. Queue-based processing where delays happen
|
| 67 |
+
3. Validation services before critical actions
|
| 68 |
+
4. Human-in-loop escalation for risky decisions
|
| 69 |
+
5. Retry-safe workflows for failures
|
| 70 |
+
6. Monitoring + audit logs
|
| 71 |
+
7. Policy/approval engine if approvals exist
|
| 72 |
+
8. Service boundaries between critical domains
|
| 73 |
+
9. Failure recovery strategy
|
| 74 |
+
10. Production-grade scalability design
|
| 75 |
+
|
| 76 |
+
-----------------------------------
|
| 77 |
+
VERY IMPORTANT
|
| 78 |
+
-----------------------------------
|
| 79 |
+
|
| 80 |
+
Return AFTER workflow steps as:
|
| 81 |
+
|
| 82 |
+
- short operational labels
|
| 83 |
+
- max 8β12 words
|
| 84 |
+
- enterprise workflow naming style
|
| 85 |
+
- production-grade system language
|
| 86 |
+
- no long explanations
|
| 87 |
+
- no paragraphs
|
| 88 |
+
- no arrows
|
| 89 |
+
- no consultant language
|
| 90 |
+
- no generic text
|
| 91 |
+
|
| 92 |
+
GOOD:
|
| 93 |
+
Policy validation engine verifies coverage
|
| 94 |
+
|
| 95 |
+
GOOD:
|
| 96 |
+
Smart approval routing triggers manager review
|
| 97 |
+
|
| 98 |
+
GOOD:
|
| 99 |
+
CRM sync service updates customer records
|
| 100 |
+
|
| 101 |
+
GOOD:
|
| 102 |
+
Queue orchestration handles async claim processing
|
| 103 |
+
|
| 104 |
+
BAD:
|
| 105 |
+
The system automatically checks whether the policy
|
| 106 |
+
is valid and then sends it for manager approval
|
| 107 |
+
|
| 108 |
+
BAD:
|
| 109 |
+
This improves operational efficiency significantly
|
| 110 |
+
|
| 111 |
+
BAD:
|
| 112 |
+
The workflow becomes scalable and production-ready
|
| 113 |
+
|
| 114 |
+
BAD:
|
| 115 |
+
Automate the process using AI
|
| 116 |
+
|
| 117 |
+
Be specific like:
|
| 118 |
+
|
| 119 |
+
GOOD:
|
| 120 |
+
Introduce document validation service before approval queue
|
| 121 |
+
|
| 122 |
+
GOOD:
|
| 123 |
+
Approval workflow triggers human escalation for exceptions
|
| 124 |
+
|
| 125 |
+
NOT:
|
| 126 |
+
|
| 127 |
+
BAD:
|
| 128 |
+
Automate process
|
| 129 |
+
|
| 130 |
+
-----------------------------------
|
| 131 |
+
DECISIONS FORMAT
|
| 132 |
+
-----------------------------------
|
| 133 |
+
|
| 134 |
+
Architecture decisions must be:
|
| 135 |
+
|
| 136 |
+
- specific
|
| 137 |
+
- technical
|
| 138 |
+
- implementation-focused
|
| 139 |
+
- production-grade
|
| 140 |
+
|
| 141 |
+
GOOD:
|
| 142 |
+
Separated validation from execution boundaries
|
| 143 |
+
|
| 144 |
+
GOOD:
|
| 145 |
+
Introduced retry-safe queue orchestration
|
| 146 |
+
|
| 147 |
+
GOOD:
|
| 148 |
+
Added policy engine for approval workflows
|
| 149 |
+
|
| 150 |
+
BAD:
|
| 151 |
+
Improved efficiency
|
| 152 |
+
|
| 153 |
+
BAD:
|
| 154 |
+
System is now better
|
| 155 |
+
|
| 156 |
+
BAD:
|
| 157 |
+
Automation helps operations
|
| 158 |
+
|
| 159 |
+
-----------------------------------
|
| 160 |
+
STRICT OUTPUT FORMAT
|
| 161 |
+
-----------------------------------
|
| 162 |
+
|
| 163 |
+
Return ONLY valid JSON.
|
| 164 |
+
|
| 165 |
+
{{
|
| 166 |
+
"after_workflow": [
|
| 167 |
+
"specific transformed step 1",
|
| 168 |
+
"specific transformed step 2",
|
| 169 |
+
"specific transformed step 3",
|
| 170 |
+
"specific transformed step 4",
|
| 171 |
+
"specific transformed step 5"
|
| 172 |
+
],
|
| 173 |
+
|
| 174 |
+
"decisions": [
|
| 175 |
+
"specific architecture decision 1",
|
| 176 |
+
"specific architecture decision 2",
|
| 177 |
+
"specific architecture decision 3",
|
| 178 |
+
"specific architecture decision 4",
|
| 179 |
+
"specific architecture decision 5"
|
| 180 |
+
]
|
| 181 |
+
}}
|
| 182 |
+
|
| 183 |
+
No markdown.
|
| 184 |
+
No explanations.
|
| 185 |
+
No headings.
|
| 186 |
+
No text outside JSON.
|
| 187 |
+
"""
|
| 188 |
+
|
| 189 |
+
response = llm.invoke(prompt)
|
| 190 |
+
|
| 191 |
+
fallback = {
|
| 192 |
+
"after_workflow": [
|
| 193 |
+
"Input ingestion service captures workflow requests",
|
| 194 |
+
"Validation engine verifies critical business rules",
|
| 195 |
+
"Queue orchestration handles async task routing",
|
| 196 |
+
"Policy engine triggers approval escalations",
|
| 197 |
+
"Observability layer tracks failures and audits"
|
| 198 |
+
],
|
| 199 |
+
"decisions": [
|
| 200 |
+
"Introduced queue-first architecture for reliability",
|
| 201 |
+
"Separated validation from execution boundaries",
|
| 202 |
+
"Added policy engine for approval workflows",
|
| 203 |
+
"Created human escalation path for exceptions",
|
| 204 |
+
"Improved monitoring with audit-safe observability"
|
| 205 |
+
]
|
| 206 |
+
}
|
| 207 |
+
|
| 208 |
+
result = safe_json_parse(
|
| 209 |
+
response.content,
|
| 210 |
+
fallback=fallback
|
| 211 |
+
)
|
| 212 |
+
|
| 213 |
+
if (
|
| 214 |
+
not isinstance(result, dict)
|
| 215 |
+
or "after_workflow" not in result
|
| 216 |
+
or "decisions" not in result
|
| 217 |
+
):
|
| 218 |
+
return fallback
|
| 219 |
+
|
| 220 |
+
if not isinstance(result["after_workflow"], list):
|
| 221 |
+
result["after_workflow"] = fallback["after_workflow"]
|
| 222 |
+
|
| 223 |
+
if not isinstance(result["decisions"], list):
|
| 224 |
+
result["decisions"] = fallback["decisions"]
|
| 225 |
+
|
| 226 |
+
return result
|
src/agents/critic.py
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from src.tools.llm import get_llm
|
| 2 |
+
from src.tools.json_parser import safe_json_parse
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def infrastructure_critic_agent(workflow_steps, architecture):
|
| 6 |
+
"""
|
| 7 |
+
Infrastructure Critic Agent
|
| 8 |
+
|
| 9 |
+
Goal:
|
| 10 |
+
Break the system before production does.
|
| 11 |
+
"""
|
| 12 |
+
|
| 13 |
+
llm = get_llm()
|
| 14 |
+
|
| 15 |
+
prompt = f"""
|
| 16 |
+
You are the INFRASTRUCTURE CRITIC Agent inside SystemForge.
|
| 17 |
+
|
| 18 |
+
You are a Principal SRE + Production Incident Reviewer.
|
| 19 |
+
|
| 20 |
+
Your job is NOT to improve the system.
|
| 21 |
+
|
| 22 |
+
Your job is to find:
|
| 23 |
+
how this architecture will fail in production.
|
| 24 |
+
|
| 25 |
+
You think like:
|
| 26 |
+
- Senior SRE
|
| 27 |
+
- Reliability Engineer
|
| 28 |
+
- Failure Investigator
|
| 29 |
+
- Platform Engineer
|
| 30 |
+
- Incident Commander
|
| 31 |
+
|
| 32 |
+
You do NOT write like a consultant.
|
| 33 |
+
|
| 34 |
+
You think like production failure already happened.
|
| 35 |
+
|
| 36 |
+
You aggressively search for:
|
| 37 |
+
|
| 38 |
+
1. Single Points of Failure
|
| 39 |
+
2. Queue failure risks
|
| 40 |
+
3. Missing retries / idempotency issues
|
| 41 |
+
4. Human bottlenecks still hidden
|
| 42 |
+
5. Missing observability
|
| 43 |
+
6. No audit trail risks
|
| 44 |
+
7. Security boundary failures
|
| 45 |
+
8. Approval workflow deadlocks
|
| 46 |
+
9. Scaling bottlenecks
|
| 47 |
+
10. Failure recovery gaps
|
| 48 |
+
11. Alerting blind spots
|
| 49 |
+
12. Cost explosion risks
|
| 50 |
+
13. Operational ownership ambiguity
|
| 51 |
+
|
| 52 |
+
Do NOT redesign.
|
| 53 |
+
|
| 54 |
+
Do NOT solve.
|
| 55 |
+
|
| 56 |
+
Do NOT suggest improvements.
|
| 57 |
+
|
| 58 |
+
Only identify:
|
| 59 |
+
what will break.
|
| 60 |
+
|
| 61 |
+
-----------------------------------
|
| 62 |
+
ORIGINAL WORKFLOW
|
| 63 |
+
-----------------------------------
|
| 64 |
+
|
| 65 |
+
{workflow_steps}
|
| 66 |
+
|
| 67 |
+
-----------------------------------
|
| 68 |
+
GENERATED ARCHITECTURE
|
| 69 |
+
-----------------------------------
|
| 70 |
+
|
| 71 |
+
{architecture}
|
| 72 |
+
|
| 73 |
+
-----------------------------------
|
| 74 |
+
VERY IMPORTANT
|
| 75 |
+
-----------------------------------
|
| 76 |
+
|
| 77 |
+
Return risks as:
|
| 78 |
+
|
| 79 |
+
- short technical findings
|
| 80 |
+
- implementation-specific
|
| 81 |
+
- production failure focused
|
| 82 |
+
- operationally realistic
|
| 83 |
+
- no vague statements
|
| 84 |
+
- no generic warnings
|
| 85 |
+
- no consultant language
|
| 86 |
+
- no explanation paragraphs
|
| 87 |
+
|
| 88 |
+
GOOD:
|
| 89 |
+
Approval queue lacks dead-letter handling
|
| 90 |
+
|
| 91 |
+
GOOD:
|
| 92 |
+
Policy validation service has no retry safety
|
| 93 |
+
|
| 94 |
+
GOOD:
|
| 95 |
+
Manual escalation path creates approval bottleneck
|
| 96 |
+
|
| 97 |
+
GOOD:
|
| 98 |
+
CRM sync failure causes silent customer mismatch
|
| 99 |
+
|
| 100 |
+
BAD:
|
| 101 |
+
System may fail
|
| 102 |
+
|
| 103 |
+
BAD:
|
| 104 |
+
This could create issues in production
|
| 105 |
+
|
| 106 |
+
BAD:
|
| 107 |
+
Workflow may not scale properly
|
| 108 |
+
|
| 109 |
+
BAD:
|
| 110 |
+
This architecture may need improvement
|
| 111 |
+
|
| 112 |
+
Every risk must feel like:
|
| 113 |
+
an actual incident review finding.
|
| 114 |
+
|
| 115 |
+
-----------------------------------
|
| 116 |
+
STRICT OUTPUT FORMAT
|
| 117 |
+
-----------------------------------
|
| 118 |
+
|
| 119 |
+
Return ONLY valid JSON.
|
| 120 |
+
|
| 121 |
+
{{
|
| 122 |
+
"risks": [
|
| 123 |
+
"specific production risk 1",
|
| 124 |
+
"specific production risk 2",
|
| 125 |
+
"specific production risk 3",
|
| 126 |
+
"specific production risk 4",
|
| 127 |
+
"specific production risk 5"
|
| 128 |
+
]
|
| 129 |
+
}}
|
| 130 |
+
|
| 131 |
+
Bad example:
|
| 132 |
+
"system may fail"
|
| 133 |
+
|
| 134 |
+
Good example:
|
| 135 |
+
"Approval queue has no dead-letter handling causing silent task loss"
|
| 136 |
+
|
| 137 |
+
Good example:
|
| 138 |
+
"Missing idempotency may trigger duplicate payment execution"
|
| 139 |
+
|
| 140 |
+
No markdown.
|
| 141 |
+
No explanations.
|
| 142 |
+
No text outside JSON.
|
| 143 |
+
"""
|
| 144 |
+
|
| 145 |
+
response = llm.invoke(prompt)
|
| 146 |
+
|
| 147 |
+
fallback = {
|
| 148 |
+
"risks": [
|
| 149 |
+
"Approval queue lacks dead-letter handling causing silent task loss",
|
| 150 |
+
"Manual escalation path creates approval bottleneck during peak load",
|
| 151 |
+
"Missing retry-safe execution may trigger duplicate business actions",
|
| 152 |
+
"No centralized audit trail creates compliance investigation risk",
|
| 153 |
+
"Missing service-level monitoring hides production degradation"
|
| 154 |
+
]
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
result = safe_json_parse(
|
| 158 |
+
response.content,
|
| 159 |
+
fallback=fallback
|
| 160 |
+
)
|
| 161 |
+
|
| 162 |
+
if (
|
| 163 |
+
not isinstance(result, dict)
|
| 164 |
+
or "risks" not in result
|
| 165 |
+
):
|
| 166 |
+
return fallback
|
| 167 |
+
|
| 168 |
+
if not isinstance(result["risks"], list):
|
| 169 |
+
result["risks"] = fallback["risks"]
|
| 170 |
+
|
| 171 |
+
return result
|
src/agents/executive_summary.py
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from src.tools.llm import get_llm
|
| 2 |
+
from src.tools.json_parser import safe_json_parse
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def executive_summary_agent(workflow_steps, final_architecture):
|
| 6 |
+
"""
|
| 7 |
+
Executive Summary Agent
|
| 8 |
+
|
| 9 |
+
Goal:
|
| 10 |
+
Convert technical architecture into business impact
|
| 11 |
+
+ generate realistic deployment metrics.
|
| 12 |
+
"""
|
| 13 |
+
|
| 14 |
+
llm = get_llm()
|
| 15 |
+
|
| 16 |
+
prompt = f"""
|
| 17 |
+
You are the EXECUTIVE SUMMARY Agent inside SystemForge.
|
| 18 |
+
|
| 19 |
+
You are a Principal Solutions Architect speaking to:
|
| 20 |
+
|
| 21 |
+
- CTO
|
| 22 |
+
- VP Engineering
|
| 23 |
+
- Head of Operations
|
| 24 |
+
- Enterprise Leadership
|
| 25 |
+
|
| 26 |
+
Your job is to translate technical architecture into:
|
| 27 |
+
|
| 28 |
+
1. deployment readiness score
|
| 29 |
+
2. automation potential
|
| 30 |
+
3. operational risk score
|
| 31 |
+
4. architecture confidence score
|
| 32 |
+
5. business impact summary
|
| 33 |
+
|
| 34 |
+
You do NOT write technical implementation details.
|
| 35 |
+
|
| 36 |
+
You do NOT write like a consultant.
|
| 37 |
+
|
| 38 |
+
You explain:
|
| 39 |
+
why this architecture matters to the business.
|
| 40 |
+
|
| 41 |
+
You focus on:
|
| 42 |
+
|
| 43 |
+
- operational efficiency
|
| 44 |
+
- execution speed
|
| 45 |
+
- approval reduction
|
| 46 |
+
- production reliability
|
| 47 |
+
- enterprise scalability
|
| 48 |
+
- compliance confidence
|
| 49 |
+
- deployment readiness
|
| 50 |
+
|
| 51 |
+
NOT:
|
| 52 |
+
|
| 53 |
+
- technical implementation details
|
| 54 |
+
- infrastructure cost anxiety
|
| 55 |
+
- generic transformation language
|
| 56 |
+
|
| 57 |
+
-----------------------------------
|
| 58 |
+
INPUT WORKFLOW
|
| 59 |
+
-----------------------------------
|
| 60 |
+
|
| 61 |
+
{workflow_steps}
|
| 62 |
+
|
| 63 |
+
-----------------------------------
|
| 64 |
+
FINAL ARCHITECTURE
|
| 65 |
+
-----------------------------------
|
| 66 |
+
|
| 67 |
+
{final_architecture}
|
| 68 |
+
|
| 69 |
+
-----------------------------------
|
| 70 |
+
YOUR TASK
|
| 71 |
+
-----------------------------------
|
| 72 |
+
|
| 73 |
+
Generate realistic executive-level metrics.
|
| 74 |
+
|
| 75 |
+
Avoid fake-looking values.
|
| 76 |
+
|
| 77 |
+
Bad:
|
| 78 |
+
100%
|
| 79 |
+
99%
|
| 80 |
+
Perfect
|
| 81 |
+
|
| 82 |
+
Good:
|
| 83 |
+
87%
|
| 84 |
+
72%
|
| 85 |
+
Low to Moderate Risk
|
| 86 |
+
91%
|
| 87 |
+
|
| 88 |
+
VERY IMPORTANT:
|
| 89 |
+
|
| 90 |
+
Business impact must be:
|
| 91 |
+
|
| 92 |
+
- short executive statements
|
| 93 |
+
- business outcome focused
|
| 94 |
+
- operationally measurable
|
| 95 |
+
- enterprise language
|
| 96 |
+
- no technical implementation detail
|
| 97 |
+
- no long explanations
|
| 98 |
+
- no consultant paragraphs
|
| 99 |
+
|
| 100 |
+
GOOD:
|
| 101 |
+
Reduced manual approvals through policy-driven automation
|
| 102 |
+
|
| 103 |
+
GOOD:
|
| 104 |
+
Improved workflow speed using async approval routing
|
| 105 |
+
|
| 106 |
+
GOOD:
|
| 107 |
+
Lowered operational failure risk with retry-safe execution
|
| 108 |
+
|
| 109 |
+
GOOD:
|
| 110 |
+
Improved compliance visibility through centralized audit logs
|
| 111 |
+
|
| 112 |
+
BAD:
|
| 113 |
+
The system architecture uses better monitoring and queues
|
| 114 |
+
|
| 115 |
+
BAD:
|
| 116 |
+
This architecture improves scalability and reliability significantly
|
| 117 |
+
|
| 118 |
+
BAD:
|
| 119 |
+
AI improves business performance
|
| 120 |
+
|
| 121 |
+
Do NOT over-focus on infrastructure cost.
|
| 122 |
+
|
| 123 |
+
Prioritize:
|
| 124 |
+
|
| 125 |
+
time reduction,
|
| 126 |
+
manual effort reduction,
|
| 127 |
+
deployment readiness,
|
| 128 |
+
operational confidence
|
| 129 |
+
|
| 130 |
+
over:
|
| 131 |
+
|
| 132 |
+
monthly cloud cost discussion.
|
| 133 |
+
|
| 134 |
+
-----------------------------------
|
| 135 |
+
STRICT OUTPUT FORMAT
|
| 136 |
+
-----------------------------------
|
| 137 |
+
|
| 138 |
+
Return ONLY valid JSON.
|
| 139 |
+
|
| 140 |
+
{{
|
| 141 |
+
"deployment_readiness": "87%",
|
| 142 |
+
"automation_potential": "74%",
|
| 143 |
+
"risk_score": "Low Risk",
|
| 144 |
+
"confidence_score": "91%",
|
| 145 |
+
|
| 146 |
+
"business_impact": [
|
| 147 |
+
"impact 1",
|
| 148 |
+
"impact 2",
|
| 149 |
+
"impact 3",
|
| 150 |
+
"impact 4",
|
| 151 |
+
"impact 5"
|
| 152 |
+
]
|
| 153 |
+
}}
|
| 154 |
+
|
| 155 |
+
No markdown.
|
| 156 |
+
No explanations.
|
| 157 |
+
No text outside JSON.
|
| 158 |
+
"""
|
| 159 |
+
|
| 160 |
+
response = llm.invoke(prompt)
|
| 161 |
+
|
| 162 |
+
fallback = {
|
| 163 |
+
"deployment_readiness": "88%",
|
| 164 |
+
"automation_potential": "76%",
|
| 165 |
+
"risk_score": "Low to Moderate Risk",
|
| 166 |
+
"confidence_score": "90%",
|
| 167 |
+
"business_impact": [
|
| 168 |
+
"Reduced manual approvals through policy-driven automation",
|
| 169 |
+
"Improved workflow speed using async approval routing",
|
| 170 |
+
"Lowered production failure risk with retry-safe execution",
|
| 171 |
+
"Improved compliance visibility through centralized audit logging",
|
| 172 |
+
"Enabled scale readiness for high-volume enterprise workflows"
|
| 173 |
+
]
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
result = safe_json_parse(
|
| 177 |
+
response.content,
|
| 178 |
+
fallback=fallback
|
| 179 |
+
)
|
| 180 |
+
|
| 181 |
+
required_keys = [
|
| 182 |
+
"deployment_readiness",
|
| 183 |
+
"automation_potential",
|
| 184 |
+
"risk_score",
|
| 185 |
+
"confidence_score",
|
| 186 |
+
"business_impact"
|
| 187 |
+
]
|
| 188 |
+
|
| 189 |
+
if not isinstance(result, dict):
|
| 190 |
+
return fallback
|
| 191 |
+
|
| 192 |
+
for key in required_keys:
|
| 193 |
+
if key not in result:
|
| 194 |
+
result[key] = fallback[key]
|
| 195 |
+
|
| 196 |
+
if not isinstance(result["business_impact"], list):
|
| 197 |
+
result["business_impact"] = fallback["business_impact"]
|
| 198 |
+
|
| 199 |
+
return result
|
src/agents/refiner.py
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from src.tools.llm import get_llm
|
| 2 |
+
from src.tools.json_parser import safe_json_parse
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def refiner_agent(workflow_steps, architecture, critic_feedback):
|
| 6 |
+
"""
|
| 7 |
+
Production Refiner Agent
|
| 8 |
+
|
| 9 |
+
Goal:
|
| 10 |
+
Convert architecture into deployment-ready production design.
|
| 11 |
+
"""
|
| 12 |
+
|
| 13 |
+
llm = get_llm()
|
| 14 |
+
|
| 15 |
+
prompt = f"""
|
| 16 |
+
You are the PRODUCTION REFINER Agent inside SystemForge.
|
| 17 |
+
|
| 18 |
+
You are a Staff+ Engineer responsible for final
|
| 19 |
+
production readiness.
|
| 20 |
+
|
| 21 |
+
Your job is to transform architecture into something
|
| 22 |
+
that can survive real-world enterprise deployment.
|
| 23 |
+
|
| 24 |
+
You think like:
|
| 25 |
+
- Staff Engineer
|
| 26 |
+
- Principal Platform Engineer
|
| 27 |
+
- Production Reliability Engineer
|
| 28 |
+
- Distributed Systems Designer
|
| 29 |
+
|
| 30 |
+
You do NOT write like a consultant.
|
| 31 |
+
|
| 32 |
+
You write like the engineer who must deploy
|
| 33 |
+
this system to production tomorrow.
|
| 34 |
+
|
| 35 |
+
You optimize for:
|
| 36 |
+
- operational excellence
|
| 37 |
+
- failure recovery
|
| 38 |
+
- auditability
|
| 39 |
+
- deployment safety
|
| 40 |
+
- observability
|
| 41 |
+
- rollback readiness
|
| 42 |
+
- compliance
|
| 43 |
+
- scale readiness
|
| 44 |
+
|
| 45 |
+
-----------------------------------
|
| 46 |
+
INPUTS
|
| 47 |
+
-----------------------------------
|
| 48 |
+
|
| 49 |
+
ORIGINAL WORKFLOW:
|
| 50 |
+
{workflow_steps}
|
| 51 |
+
|
| 52 |
+
ARCHITECT OUTPUT:
|
| 53 |
+
{architecture}
|
| 54 |
+
|
| 55 |
+
CRITIC FEEDBACK:
|
| 56 |
+
{critic_feedback}
|
| 57 |
+
|
| 58 |
+
-----------------------------------
|
| 59 |
+
YOUR TASK
|
| 60 |
+
-----------------------------------
|
| 61 |
+
|
| 62 |
+
Resolve the critic risks by adding:
|
| 63 |
+
|
| 64 |
+
1. Dead Letter Queues (DLQ)
|
| 65 |
+
2. Retry-safe execution paths
|
| 66 |
+
3. Idempotent workflows
|
| 67 |
+
4. Audit logging
|
| 68 |
+
5. Distributed tracing
|
| 69 |
+
6. Monitoring + alerting
|
| 70 |
+
7. Human override paths
|
| 71 |
+
8. Rollback safety
|
| 72 |
+
9. Confidence scoring
|
| 73 |
+
10. Failure isolation boundaries
|
| 74 |
+
11. Circuit breaker protection
|
| 75 |
+
12. Deployment readiness strategy
|
| 76 |
+
|
| 77 |
+
You MUST also create final architecture layers.
|
| 78 |
+
|
| 79 |
+
-----------------------------------
|
| 80 |
+
VERY IMPORTANT
|
| 81 |
+
-----------------------------------
|
| 82 |
+
|
| 83 |
+
Return improvements as:
|
| 84 |
+
|
| 85 |
+
- short technical improvements
|
| 86 |
+
- production deployment focused
|
| 87 |
+
- implementation-specific
|
| 88 |
+
- enterprise operational language
|
| 89 |
+
- no generic explanations
|
| 90 |
+
- no consultant language
|
| 91 |
+
- no vague statements
|
| 92 |
+
- no paragraphs
|
| 93 |
+
|
| 94 |
+
GOOD:
|
| 95 |
+
Added dead-letter queue for approval failures
|
| 96 |
+
|
| 97 |
+
GOOD:
|
| 98 |
+
Introduced idempotent retry-safe payment execution
|
| 99 |
+
|
| 100 |
+
GOOD:
|
| 101 |
+
Enabled audit-safe approval decision logging
|
| 102 |
+
|
| 103 |
+
GOOD:
|
| 104 |
+
Added rollback workflow for failed ERP sync
|
| 105 |
+
|
| 106 |
+
BAD:
|
| 107 |
+
Improved monitoring
|
| 108 |
+
|
| 109 |
+
BAD:
|
| 110 |
+
System is now more reliable
|
| 111 |
+
|
| 112 |
+
BAD:
|
| 113 |
+
Added better observability for production
|
| 114 |
+
|
| 115 |
+
BAD:
|
| 116 |
+
Improved deployment quality
|
| 117 |
+
|
| 118 |
+
Each improvement must feel like:
|
| 119 |
+
a real production deployment change.
|
| 120 |
+
|
| 121 |
+
-----------------------------------
|
| 122 |
+
ARCHITECTURE LAYERS RULES
|
| 123 |
+
-----------------------------------
|
| 124 |
+
|
| 125 |
+
Architecture layers must be:
|
| 126 |
+
|
| 127 |
+
- production-grade
|
| 128 |
+
- short + clear
|
| 129 |
+
- system boundary focused
|
| 130 |
+
- implementation-ready
|
| 131 |
+
- enterprise architecture naming style
|
| 132 |
+
|
| 133 |
+
GOOD:
|
| 134 |
+
Workflow Orchestration Layer
|
| 135 |
+
|
| 136 |
+
GOOD:
|
| 137 |
+
Decision + Validation Layer
|
| 138 |
+
|
| 139 |
+
GOOD:
|
| 140 |
+
Production Reliability Layer
|
| 141 |
+
|
| 142 |
+
BAD:
|
| 143 |
+
AI Smart Layer
|
| 144 |
+
|
| 145 |
+
BAD:
|
| 146 |
+
Automation System Layer
|
| 147 |
+
|
| 148 |
+
BAD:
|
| 149 |
+
Technology Improvement Layer
|
| 150 |
+
|
| 151 |
+
Descriptions must be concise and technical.
|
| 152 |
+
|
| 153 |
+
Items must be:
|
| 154 |
+
|
| 155 |
+
- real services
|
| 156 |
+
- real components
|
| 157 |
+
- real infrastructure boundaries
|
| 158 |
+
|
| 159 |
+
GOOD:
|
| 160 |
+
Approval Orchestration Engine
|
| 161 |
+
|
| 162 |
+
GOOD:
|
| 163 |
+
Dead Letter Queue + Retry Engine
|
| 164 |
+
|
| 165 |
+
GOOD:
|
| 166 |
+
Observability + Audit Logging
|
| 167 |
+
|
| 168 |
+
BAD:
|
| 169 |
+
AI Automation Tool
|
| 170 |
+
|
| 171 |
+
BAD:
|
| 172 |
+
Smart Process System
|
| 173 |
+
|
| 174 |
+
-----------------------------------
|
| 175 |
+
STRICT OUTPUT FORMAT
|
| 176 |
+
-----------------------------------
|
| 177 |
+
|
| 178 |
+
Return ONLY valid JSON.
|
| 179 |
+
|
| 180 |
+
{{
|
| 181 |
+
"improvements": [
|
| 182 |
+
"specific improvement 1",
|
| 183 |
+
"specific improvement 2",
|
| 184 |
+
"specific improvement 3",
|
| 185 |
+
"specific improvement 4",
|
| 186 |
+
"specific improvement 5"
|
| 187 |
+
],
|
| 188 |
+
|
| 189 |
+
"architecture_layers": [
|
| 190 |
+
{{
|
| 191 |
+
"title": "Layer Name",
|
| 192 |
+
"description": "Production-grade explanation",
|
| 193 |
+
"items": [
|
| 194 |
+
"specific item 1",
|
| 195 |
+
"specific item 2",
|
| 196 |
+
"specific item 3"
|
| 197 |
+
]
|
| 198 |
+
}}
|
| 199 |
+
]
|
| 200 |
+
}}
|
| 201 |
+
|
| 202 |
+
No markdown.
|
| 203 |
+
No explanations.
|
| 204 |
+
No text outside JSON.
|
| 205 |
+
"""
|
| 206 |
+
|
| 207 |
+
response = llm.invoke(prompt)
|
| 208 |
+
|
| 209 |
+
fallback = {
|
| 210 |
+
"improvements": [
|
| 211 |
+
"Added dead-letter queue for failed approval events",
|
| 212 |
+
"Introduced idempotent retry-safe execution for approvals",
|
| 213 |
+
"Enabled centralized audit logs and distributed tracing",
|
| 214 |
+
"Added circuit breaker protection and service isolation boundaries",
|
| 215 |
+
"Improved monitoring with rollback readiness and human override"
|
| 216 |
+
],
|
| 217 |
+
"architecture_layers": [
|
| 218 |
+
{
|
| 219 |
+
"title": "Workflow Orchestration Layer",
|
| 220 |
+
"description": "Captures workflow inputs and manages approval lifecycle safely",
|
| 221 |
+
"items": [
|
| 222 |
+
"Workflow Intake Service",
|
| 223 |
+
"Approval Orchestration Engine",
|
| 224 |
+
"Human Escalation Manager"
|
| 225 |
+
]
|
| 226 |
+
},
|
| 227 |
+
{
|
| 228 |
+
"title": "Decision + Validation Layer",
|
| 229 |
+
"description": "Validates business rules and executes policy decisions",
|
| 230 |
+
"items": [
|
| 231 |
+
"Validation Engine",
|
| 232 |
+
"Policy Decision Service",
|
| 233 |
+
"Approval Routing Engine"
|
| 234 |
+
]
|
| 235 |
+
},
|
| 236 |
+
{
|
| 237 |
+
"title": "Inference + Compute Layer",
|
| 238 |
+
"description": "Handles production LLM inference using GPU-backed serving",
|
| 239 |
+
"items": [
|
| 240 |
+
"Qwen 2.5 Inference",
|
| 241 |
+
"vLLM OpenAI-Compatible Serving",
|
| 242 |
+
"AMD MI300X ROCm Runtime"
|
| 243 |
+
]
|
| 244 |
+
},
|
| 245 |
+
{
|
| 246 |
+
"title": "Production Reliability Layer",
|
| 247 |
+
"description": "Provides retries, observability, compliance, and failure recovery",
|
| 248 |
+
"items": [
|
| 249 |
+
"Dead Letter Queue + Retry Engine",
|
| 250 |
+
"PostgreSQL + Redis",
|
| 251 |
+
"Observability + Audit Logging"
|
| 252 |
+
]
|
| 253 |
+
}
|
| 254 |
+
]
|
| 255 |
+
}
|
| 256 |
+
|
| 257 |
+
result = safe_json_parse(
|
| 258 |
+
response.content,
|
| 259 |
+
fallback=fallback
|
| 260 |
+
)
|
| 261 |
+
|
| 262 |
+
if (
|
| 263 |
+
not isinstance(result, dict)
|
| 264 |
+
or "improvements" not in result
|
| 265 |
+
or "architecture_layers" not in result
|
| 266 |
+
):
|
| 267 |
+
return fallback
|
| 268 |
+
|
| 269 |
+
if not isinstance(result["improvements"], list):
|
| 270 |
+
result["improvements"] = fallback["improvements"]
|
| 271 |
+
|
| 272 |
+
if not isinstance(result["architecture_layers"], list):
|
| 273 |
+
result["architecture_layers"] = fallback["architecture_layers"]
|
| 274 |
+
|
| 275 |
+
return result
|
src/api/main.py
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI, HTTPException
|
| 2 |
+
from pydantic import BaseModel
|
| 3 |
+
from fastapi.middleware.cors import CORSMiddleware
|
| 4 |
+
from fastapi.responses import FileResponse
|
| 5 |
+
|
| 6 |
+
from src.workflows.crew import run_systemforge
|
| 7 |
+
from src.api.pdf_generator import generate_architecture_pdf
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
app = FastAPI(
|
| 11 |
+
title="SystemForge API"
|
| 12 |
+
)
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
# CORS for Next.js frontend
|
| 16 |
+
app.add_middleware(
|
| 17 |
+
CORSMiddleware,
|
| 18 |
+
allow_origins=[
|
| 19 |
+
"http://localhost:3000",
|
| 20 |
+
],
|
| 21 |
+
allow_credentials=True,
|
| 22 |
+
allow_methods=["*"],
|
| 23 |
+
allow_headers=["*"],
|
| 24 |
+
)
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
class WorkflowRequest(BaseModel):
|
| 28 |
+
workflow: list[str]
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
@app.get("/")
|
| 32 |
+
def root():
|
| 33 |
+
return {
|
| 34 |
+
"message": "SystemForge API Running"
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
@app.post("/run-systemforge")
|
| 39 |
+
def generate_architecture(
|
| 40 |
+
request: WorkflowRequest
|
| 41 |
+
):
|
| 42 |
+
try:
|
| 43 |
+
if not request.workflow:
|
| 44 |
+
raise HTTPException(
|
| 45 |
+
status_code=400,
|
| 46 |
+
detail="Workflow steps cannot be empty"
|
| 47 |
+
)
|
| 48 |
+
|
| 49 |
+
result = run_systemforge(
|
| 50 |
+
request.workflow
|
| 51 |
+
)
|
| 52 |
+
|
| 53 |
+
return result
|
| 54 |
+
|
| 55 |
+
except HTTPException:
|
| 56 |
+
raise
|
| 57 |
+
|
| 58 |
+
except Exception as e:
|
| 59 |
+
print(f"SystemForge Error: {str(e)}")
|
| 60 |
+
|
| 61 |
+
raise HTTPException(
|
| 62 |
+
status_code=500,
|
| 63 |
+
detail="Failed to generate architecture"
|
| 64 |
+
)
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
@app.post("/download-report")
|
| 68 |
+
def download_report(
|
| 69 |
+
request: WorkflowRequest
|
| 70 |
+
):
|
| 71 |
+
"""
|
| 72 |
+
Generates PDF architecture report
|
| 73 |
+
and returns downloadable file
|
| 74 |
+
"""
|
| 75 |
+
|
| 76 |
+
try:
|
| 77 |
+
if not request.workflow:
|
| 78 |
+
raise HTTPException(
|
| 79 |
+
status_code=400,
|
| 80 |
+
detail="Workflow steps cannot be empty"
|
| 81 |
+
)
|
| 82 |
+
|
| 83 |
+
# Generate architecture first
|
| 84 |
+
result = run_systemforge(
|
| 85 |
+
request.workflow
|
| 86 |
+
)
|
| 87 |
+
|
| 88 |
+
# Create PDF
|
| 89 |
+
file_path = generate_architecture_pdf(
|
| 90 |
+
data=result,
|
| 91 |
+
filename="architecture_report.pdf"
|
| 92 |
+
)
|
| 93 |
+
|
| 94 |
+
return FileResponse(
|
| 95 |
+
path=file_path,
|
| 96 |
+
filename="SystemForge_Architecture_Report.pdf",
|
| 97 |
+
media_type="application/pdf"
|
| 98 |
+
)
|
| 99 |
+
|
| 100 |
+
except HTTPException:
|
| 101 |
+
raise
|
| 102 |
+
|
| 103 |
+
except Exception as e:
|
| 104 |
+
print(f"PDF Generation Error: {str(e)}")
|
| 105 |
+
|
| 106 |
+
raise HTTPException(
|
| 107 |
+
status_code=500,
|
| 108 |
+
detail="Failed to generate report"
|
| 109 |
+
)
|
src/api/pdf_generator.py
ADDED
|
@@ -0,0 +1,444 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from datetime import datetime
|
| 2 |
+
|
| 3 |
+
from reportlab.platypus import (
|
| 4 |
+
SimpleDocTemplate,
|
| 5 |
+
Paragraph,
|
| 6 |
+
Spacer,
|
| 7 |
+
Table,
|
| 8 |
+
TableStyle,
|
| 9 |
+
)
|
| 10 |
+
|
| 11 |
+
from reportlab.lib.styles import (
|
| 12 |
+
getSampleStyleSheet,
|
| 13 |
+
ParagraphStyle,
|
| 14 |
+
)
|
| 15 |
+
|
| 16 |
+
from reportlab.lib.pagesizes import A4
|
| 17 |
+
from reportlab.lib.enums import TA_CENTER
|
| 18 |
+
from reportlab.lib import colors
|
| 19 |
+
from reportlab.lib.units import inch
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
def generate_architecture_pdf(
|
| 23 |
+
data,
|
| 24 |
+
filename="architecture_report.pdf"
|
| 25 |
+
):
|
| 26 |
+
"""
|
| 27 |
+
Premium Executive PDF
|
| 28 |
+
Compact + Professional + CTO Ready
|
| 29 |
+
|
| 30 |
+
Includes:
|
| 31 |
+
- Cover
|
| 32 |
+
- Before / After Workflow
|
| 33 |
+
- Metrics Dashboard
|
| 34 |
+
- Architecture Blueprint
|
| 35 |
+
- Executive Summary
|
| 36 |
+
"""
|
| 37 |
+
|
| 38 |
+
# =====================================================
|
| 39 |
+
# COLORS
|
| 40 |
+
# =====================================================
|
| 41 |
+
|
| 42 |
+
PRIMARY = colors.HexColor("#2563EB")
|
| 43 |
+
SUCCESS = colors.HexColor("#16A34A")
|
| 44 |
+
WARNING = colors.HexColor("#D97706")
|
| 45 |
+
PURPLE = colors.HexColor("#7C3AED")
|
| 46 |
+
|
| 47 |
+
TEXT = colors.HexColor("#0F172A")
|
| 48 |
+
MUTED = colors.HexColor("#64748B")
|
| 49 |
+
|
| 50 |
+
BORDER = colors.HexColor("#E2E8F0")
|
| 51 |
+
|
| 52 |
+
LIGHT_BLUE = colors.HexColor("#EFF6FF")
|
| 53 |
+
LIGHT_RED = colors.HexColor("#FEF2F2")
|
| 54 |
+
LIGHT_BG = colors.HexColor("#F8FAFC")
|
| 55 |
+
EXEC_BG = colors.HexColor("#FAF5FF")
|
| 56 |
+
|
| 57 |
+
# =====================================================
|
| 58 |
+
# DOCUMENT
|
| 59 |
+
# =====================================================
|
| 60 |
+
|
| 61 |
+
doc = SimpleDocTemplate(
|
| 62 |
+
filename,
|
| 63 |
+
pagesize=A4,
|
| 64 |
+
leftMargin=32,
|
| 65 |
+
rightMargin=32,
|
| 66 |
+
topMargin=32,
|
| 67 |
+
bottomMargin=32,
|
| 68 |
+
)
|
| 69 |
+
|
| 70 |
+
styles = getSampleStyleSheet()
|
| 71 |
+
|
| 72 |
+
# =====================================================
|
| 73 |
+
# TYPOGRAPHY
|
| 74 |
+
# =====================================================
|
| 75 |
+
|
| 76 |
+
title_style = ParagraphStyle(
|
| 77 |
+
"Title",
|
| 78 |
+
parent=styles["Title"],
|
| 79 |
+
fontName="Helvetica-Bold",
|
| 80 |
+
fontSize=22,
|
| 81 |
+
leading=28,
|
| 82 |
+
alignment=TA_CENTER,
|
| 83 |
+
textColor=TEXT,
|
| 84 |
+
spaceAfter=8,
|
| 85 |
+
)
|
| 86 |
+
|
| 87 |
+
subtitle_style = ParagraphStyle(
|
| 88 |
+
"Subtitle",
|
| 89 |
+
parent=styles["Normal"],
|
| 90 |
+
fontSize=10,
|
| 91 |
+
leading=14,
|
| 92 |
+
alignment=TA_CENTER,
|
| 93 |
+
textColor=MUTED,
|
| 94 |
+
spaceAfter=6,
|
| 95 |
+
)
|
| 96 |
+
|
| 97 |
+
section_style = ParagraphStyle(
|
| 98 |
+
"Section",
|
| 99 |
+
parent=styles["Heading2"],
|
| 100 |
+
fontName="Helvetica-Bold",
|
| 101 |
+
fontSize=13,
|
| 102 |
+
leading=18,
|
| 103 |
+
textColor=PRIMARY,
|
| 104 |
+
spaceBefore=10,
|
| 105 |
+
spaceAfter=8,
|
| 106 |
+
)
|
| 107 |
+
|
| 108 |
+
body_style = ParagraphStyle(
|
| 109 |
+
"Body",
|
| 110 |
+
parent=styles["BodyText"],
|
| 111 |
+
fontSize=10,
|
| 112 |
+
leading=14,
|
| 113 |
+
textColor=TEXT,
|
| 114 |
+
spaceAfter=4,
|
| 115 |
+
)
|
| 116 |
+
|
| 117 |
+
metric_value_style = ParagraphStyle(
|
| 118 |
+
"MetricValue",
|
| 119 |
+
parent=styles["BodyText"],
|
| 120 |
+
fontName="Helvetica-Bold",
|
| 121 |
+
fontSize=14,
|
| 122 |
+
alignment=TA_CENTER,
|
| 123 |
+
textColor=TEXT,
|
| 124 |
+
)
|
| 125 |
+
|
| 126 |
+
metric_label_style = ParagraphStyle(
|
| 127 |
+
"MetricLabel",
|
| 128 |
+
parent=styles["BodyText"],
|
| 129 |
+
fontSize=8,
|
| 130 |
+
alignment=TA_CENTER,
|
| 131 |
+
textColor=MUTED,
|
| 132 |
+
)
|
| 133 |
+
|
| 134 |
+
content = []
|
| 135 |
+
|
| 136 |
+
# =====================================================
|
| 137 |
+
# COVER SECTION
|
| 138 |
+
# =====================================================
|
| 139 |
+
|
| 140 |
+
content.append(
|
| 141 |
+
Paragraph(
|
| 142 |
+
"SYSTEMFORGE AI",
|
| 143 |
+
title_style
|
| 144 |
+
)
|
| 145 |
+
)
|
| 146 |
+
|
| 147 |
+
content.append(
|
| 148 |
+
Paragraph(
|
| 149 |
+
"Production Architecture Blueprint",
|
| 150 |
+
subtitle_style
|
| 151 |
+
)
|
| 152 |
+
)
|
| 153 |
+
|
| 154 |
+
content.append(
|
| 155 |
+
Paragraph(
|
| 156 |
+
f"Generated on: {datetime.now().strftime('%d %B %Y')}",
|
| 157 |
+
subtitle_style
|
| 158 |
+
)
|
| 159 |
+
)
|
| 160 |
+
|
| 161 |
+
content.append(
|
| 162 |
+
Paragraph(
|
| 163 |
+
"Confidential β Internal Architecture Review",
|
| 164 |
+
subtitle_style
|
| 165 |
+
)
|
| 166 |
+
)
|
| 167 |
+
|
| 168 |
+
content.append(Spacer(1, 0.15 * inch))
|
| 169 |
+
|
| 170 |
+
hero = Table(
|
| 171 |
+
[[
|
| 172 |
+
Paragraph(
|
| 173 |
+
"Workflow Redesign + Production Validation Engine",
|
| 174 |
+
body_style
|
| 175 |
+
)
|
| 176 |
+
]],
|
| 177 |
+
colWidths=[500]
|
| 178 |
+
)
|
| 179 |
+
|
| 180 |
+
hero.setStyle(
|
| 181 |
+
TableStyle([
|
| 182 |
+
("BACKGROUND", (0, 0), (-1, -1), LIGHT_BG),
|
| 183 |
+
("BOX", (0, 0), (-1, -1), 1, PRIMARY),
|
| 184 |
+
("LEFTPADDING", (0, 0), (-1, -1), 14),
|
| 185 |
+
("TOPPADDING", (0, 0), (-1, -1), 12),
|
| 186 |
+
("BOTTOMPADDING", (0, 0), (-1, -1), 12),
|
| 187 |
+
])
|
| 188 |
+
)
|
| 189 |
+
|
| 190 |
+
content.append(hero)
|
| 191 |
+
content.append(Spacer(1, 0.20 * inch))
|
| 192 |
+
|
| 193 |
+
# =====================================================
|
| 194 |
+
# BEFORE / AFTER WORKFLOW
|
| 195 |
+
# =====================================================
|
| 196 |
+
|
| 197 |
+
before = data.get(
|
| 198 |
+
"workflowTransformation",
|
| 199 |
+
{}
|
| 200 |
+
).get("before", [])
|
| 201 |
+
|
| 202 |
+
after = data.get(
|
| 203 |
+
"workflowTransformation",
|
| 204 |
+
{}
|
| 205 |
+
).get("after", [])
|
| 206 |
+
|
| 207 |
+
before_html = "<br/>".join(
|
| 208 |
+
[f"β’ {step}" for step in before]
|
| 209 |
+
)
|
| 210 |
+
|
| 211 |
+
after_html = "<br/>".join(
|
| 212 |
+
[f"β’ {step}" for step in after]
|
| 213 |
+
)
|
| 214 |
+
|
| 215 |
+
content.append(
|
| 216 |
+
Paragraph(
|
| 217 |
+
"Before β After Workflow Transformation",
|
| 218 |
+
section_style
|
| 219 |
+
)
|
| 220 |
+
)
|
| 221 |
+
|
| 222 |
+
before_after = Table(
|
| 223 |
+
[[
|
| 224 |
+
Paragraph(
|
| 225 |
+
f"<b>BEFORE β MANUAL WORKFLOW</b><br/><br/>{before_html}",
|
| 226 |
+
body_style
|
| 227 |
+
),
|
| 228 |
+
Paragraph(
|
| 229 |
+
f"<b>AFTER β AI NATIVE SYSTEM</b><br/><br/>{after_html}",
|
| 230 |
+
body_style
|
| 231 |
+
)
|
| 232 |
+
]],
|
| 233 |
+
colWidths=[250, 250]
|
| 234 |
+
)
|
| 235 |
+
|
| 236 |
+
before_after.setStyle(
|
| 237 |
+
TableStyle([
|
| 238 |
+
("BACKGROUND", (0, 0), (0, 0), LIGHT_RED),
|
| 239 |
+
("BACKGROUND", (1, 0), (1, 0), LIGHT_BLUE),
|
| 240 |
+
("BOX", (0, 0), (-1, -1), 1, BORDER),
|
| 241 |
+
("INNERGRID", (0, 0), (-1, -1), 0.5, BORDER),
|
| 242 |
+
("VALIGN", (0, 0), (-1, -1), "TOP"),
|
| 243 |
+
("LEFTPADDING", (0, 0), (-1, -1), 12),
|
| 244 |
+
("TOPPADDING", (0, 0), (-1, -1), 12),
|
| 245 |
+
("BOTTOMPADDING", (0, 0), (-1, -1), 12),
|
| 246 |
+
])
|
| 247 |
+
)
|
| 248 |
+
|
| 249 |
+
content.append(before_after)
|
| 250 |
+
content.append(Spacer(1, 0.20 * inch))
|
| 251 |
+
|
| 252 |
+
# =====================================================
|
| 253 |
+
# METRICS DASHBOARD
|
| 254 |
+
# =====================================================
|
| 255 |
+
|
| 256 |
+
content.append(
|
| 257 |
+
Paragraph(
|
| 258 |
+
"Final System Metrics",
|
| 259 |
+
section_style
|
| 260 |
+
)
|
| 261 |
+
)
|
| 262 |
+
|
| 263 |
+
metrics = data.get(
|
| 264 |
+
"finalMetrics",
|
| 265 |
+
{}
|
| 266 |
+
)
|
| 267 |
+
|
| 268 |
+
metric_items = [
|
| 269 |
+
(
|
| 270 |
+
metrics.get(
|
| 271 |
+
"deploymentReadiness",
|
| 272 |
+
"β"
|
| 273 |
+
),
|
| 274 |
+
"Deployment Readiness",
|
| 275 |
+
SUCCESS,
|
| 276 |
+
),
|
| 277 |
+
(
|
| 278 |
+
metrics.get(
|
| 279 |
+
"automationPotential",
|
| 280 |
+
"β"
|
| 281 |
+
),
|
| 282 |
+
"Automation Potential",
|
| 283 |
+
PRIMARY,
|
| 284 |
+
),
|
| 285 |
+
(
|
| 286 |
+
metrics.get(
|
| 287 |
+
"riskScore",
|
| 288 |
+
"β"
|
| 289 |
+
),
|
| 290 |
+
"Risk Score",
|
| 291 |
+
WARNING,
|
| 292 |
+
),
|
| 293 |
+
]
|
| 294 |
+
|
| 295 |
+
cards = []
|
| 296 |
+
|
| 297 |
+
for value, label, color in metric_items:
|
| 298 |
+
card = Table(
|
| 299 |
+
[[
|
| 300 |
+
Paragraph(
|
| 301 |
+
str(value),
|
| 302 |
+
metric_value_style
|
| 303 |
+
)
|
| 304 |
+
],
|
| 305 |
+
[
|
| 306 |
+
Paragraph(
|
| 307 |
+
label,
|
| 308 |
+
metric_label_style
|
| 309 |
+
)
|
| 310 |
+
]],
|
| 311 |
+
colWidths=[155]
|
| 312 |
+
)
|
| 313 |
+
|
| 314 |
+
card.setStyle(
|
| 315 |
+
TableStyle([
|
| 316 |
+
("BOX", (0, 0), (-1, -1), 1, color),
|
| 317 |
+
("TOPPADDING", (0, 0), (-1, -1), 10),
|
| 318 |
+
("BOTTOMPADDING", (0, 0), (-1, -1), 10),
|
| 319 |
+
])
|
| 320 |
+
)
|
| 321 |
+
|
| 322 |
+
cards.append(card)
|
| 323 |
+
|
| 324 |
+
content.append(
|
| 325 |
+
Table([cards])
|
| 326 |
+
)
|
| 327 |
+
|
| 328 |
+
content.append(Spacer(1, 0.20 * inch))
|
| 329 |
+
|
| 330 |
+
# =====================================================
|
| 331 |
+
# ARCHITECTURE BLUEPRINT
|
| 332 |
+
# =====================================================
|
| 333 |
+
|
| 334 |
+
content.append(
|
| 335 |
+
Paragraph(
|
| 336 |
+
"Final Architecture Blueprint",
|
| 337 |
+
section_style
|
| 338 |
+
)
|
| 339 |
+
)
|
| 340 |
+
|
| 341 |
+
layers = data.get(
|
| 342 |
+
"architectureLayers",
|
| 343 |
+
[]
|
| 344 |
+
)
|
| 345 |
+
|
| 346 |
+
for layer in layers:
|
| 347 |
+
layer_card = Table(
|
| 348 |
+
[[
|
| 349 |
+
Paragraph(
|
| 350 |
+
f"<b>{layer.get('title')}</b><br/><br/>{layer.get('description')}",
|
| 351 |
+
body_style
|
| 352 |
+
)
|
| 353 |
+
]],
|
| 354 |
+
colWidths=[500]
|
| 355 |
+
)
|
| 356 |
+
|
| 357 |
+
layer_card.setStyle(
|
| 358 |
+
TableStyle([
|
| 359 |
+
("BOX", (0, 0), (-1, -1), 1, BORDER),
|
| 360 |
+
("LEFTPADDING", (0, 0), (-1, -1), 12),
|
| 361 |
+
("TOPPADDING", (0, 0), (-1, -1), 10),
|
| 362 |
+
("BOTTOMPADDING", (0, 0), (-1, -1), 10),
|
| 363 |
+
])
|
| 364 |
+
)
|
| 365 |
+
|
| 366 |
+
content.append(layer_card)
|
| 367 |
+
content.append(
|
| 368 |
+
Spacer(1, 0.10 * inch)
|
| 369 |
+
)
|
| 370 |
+
|
| 371 |
+
# =====================================================
|
| 372 |
+
# EXECUTIVE SUMMARY
|
| 373 |
+
# =====================================================
|
| 374 |
+
|
| 375 |
+
executive = data.get(
|
| 376 |
+
"executiveSummary",
|
| 377 |
+
{}
|
| 378 |
+
)
|
| 379 |
+
|
| 380 |
+
executive_points = executive.get(
|
| 381 |
+
"decisions",
|
| 382 |
+
[]
|
| 383 |
+
)
|
| 384 |
+
|
| 385 |
+
if executive_points:
|
| 386 |
+
content.append(
|
| 387 |
+
Spacer(1, 0.15 * inch)
|
| 388 |
+
)
|
| 389 |
+
|
| 390 |
+
content.append(
|
| 391 |
+
Paragraph(
|
| 392 |
+
"Executive Summary",
|
| 393 |
+
section_style
|
| 394 |
+
)
|
| 395 |
+
)
|
| 396 |
+
|
| 397 |
+
executive_html = "<br/>".join(
|
| 398 |
+
[f"β’ {point}" for point in executive_points]
|
| 399 |
+
)
|
| 400 |
+
|
| 401 |
+
executive_card = Table(
|
| 402 |
+
[[
|
| 403 |
+
Paragraph(
|
| 404 |
+
f"<b>Business Impact + ROI</b><br/><br/>{executive_html}",
|
| 405 |
+
body_style
|
| 406 |
+
)
|
| 407 |
+
]],
|
| 408 |
+
colWidths=[500]
|
| 409 |
+
)
|
| 410 |
+
|
| 411 |
+
executive_card.setStyle(
|
| 412 |
+
TableStyle([
|
| 413 |
+
("BACKGROUND", (0, 0), (-1, -1), EXEC_BG),
|
| 414 |
+
("BOX", (0, 0), (-1, -1), 1, PURPLE),
|
| 415 |
+
("LEFTPADDING", (0, 0), (-1, -1), 14),
|
| 416 |
+
("TOPPADDING", (0, 0), (-1, -1), 12),
|
| 417 |
+
("BOTTOMPADDING", (0, 0), (-1, -1), 12),
|
| 418 |
+
])
|
| 419 |
+
)
|
| 420 |
+
|
| 421 |
+
content.append(executive_card)
|
| 422 |
+
|
| 423 |
+
# =====================================================
|
| 424 |
+
# FOOTER
|
| 425 |
+
# =====================================================
|
| 426 |
+
|
| 427 |
+
content.append(
|
| 428 |
+
Spacer(1, 0.20 * inch)
|
| 429 |
+
)
|
| 430 |
+
|
| 431 |
+
content.append(
|
| 432 |
+
Paragraph(
|
| 433 |
+
"Generated by SystemForge AI β Enterprise Workflow Redesign Engine",
|
| 434 |
+
subtitle_style
|
| 435 |
+
)
|
| 436 |
+
)
|
| 437 |
+
|
| 438 |
+
# =====================================================
|
| 439 |
+
# BUILD
|
| 440 |
+
# =====================================================
|
| 441 |
+
|
| 442 |
+
doc.build(content)
|
| 443 |
+
|
| 444 |
+
return filename
|
src/config/agents.yaml
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'''
|
| 2 |
+
architect:
|
| 3 |
+
role: Principal Software Architect
|
| 4 |
+
goal: Design production-grade architecture plans
|
| 5 |
+
|
| 6 |
+
critic:
|
| 7 |
+
role: Senior Site Reliability Engineer
|
| 8 |
+
goal: Detect scalability and reliability risks
|
| 9 |
+
|
| 10 |
+
refiner:
|
| 11 |
+
role: Autonomous Recovery Engine
|
| 12 |
+
goal: Improve weak architecture decisions automatically
|
| 13 |
+
'''
|
src/config/tasks.yaml
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'''
|
| 2 |
+
draft_task:
|
| 3 |
+
description: "Create architecture blueprint from project idea"
|
| 4 |
+
|
| 5 |
+
review_task:
|
| 6 |
+
description: "Identify SPOFs, bottlenecks, and observability gaps"
|
| 7 |
+
|
| 8 |
+
finalize_task:
|
| 9 |
+
description: "Apply improvements and produce refined architecture"
|
| 10 |
+
'''
|
src/prompts/workflow_prompt.py
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
WORKFLOW_TRANSFORMATION_PROMPT = """
|
| 2 |
+
You are SystemForge AI β an elite production systems architect.
|
| 3 |
+
|
| 4 |
+
Your job is to redesign messy manual business workflows into
|
| 5 |
+
production-grade AI-native operational systems.
|
| 6 |
+
|
| 7 |
+
You do NOT explain like a consultant.
|
| 8 |
+
|
| 9 |
+
You think like:
|
| 10 |
+
|
| 11 |
+
- Principal Systems Architect
|
| 12 |
+
- Staff Platform Engineer
|
| 13 |
+
- Enterprise Workflow Designer
|
| 14 |
+
- Production AI Operator
|
| 15 |
+
|
| 16 |
+
Your output must be:
|
| 17 |
+
|
| 18 |
+
- structured
|
| 19 |
+
- operational
|
| 20 |
+
- production-ready
|
| 21 |
+
- implementation-focused
|
| 22 |
+
- enterprise-grade
|
| 23 |
+
|
| 24 |
+
--------------------------------------------------
|
| 25 |
+
TASK
|
| 26 |
+
--------------------------------------------------
|
| 27 |
+
|
| 28 |
+
Given a manual workflow, redesign it into a scalable,
|
| 29 |
+
AI-native production workflow.
|
| 30 |
+
|
| 31 |
+
You must transform:
|
| 32 |
+
|
| 33 |
+
BEFORE β AFTER
|
| 34 |
+
|
| 35 |
+
from:
|
| 36 |
+
|
| 37 |
+
manual operations,
|
| 38 |
+
spreadsheets,
|
| 39 |
+
email approvals,
|
| 40 |
+
human bottlenecks,
|
| 41 |
+
copy-paste processes
|
| 42 |
+
|
| 43 |
+
into:
|
| 44 |
+
|
| 45 |
+
automation layers,
|
| 46 |
+
validation services,
|
| 47 |
+
decision engines,
|
| 48 |
+
approval routing,
|
| 49 |
+
queue-based systems,
|
| 50 |
+
human fallback paths,
|
| 51 |
+
CRM / ERP sync,
|
| 52 |
+
production architecture patterns
|
| 53 |
+
|
| 54 |
+
--------------------------------------------------
|
| 55 |
+
VERY IMPORTANT
|
| 56 |
+
--------------------------------------------------
|
| 57 |
+
|
| 58 |
+
Return AFTER workflow steps as:
|
| 59 |
+
|
| 60 |
+
- short operational labels
|
| 61 |
+
- max 8β12 words
|
| 62 |
+
- enterprise workflow naming style
|
| 63 |
+
- production-grade system language
|
| 64 |
+
- no long explanations
|
| 65 |
+
- no paragraphs
|
| 66 |
+
- no arrows
|
| 67 |
+
- no consultant language
|
| 68 |
+
- no generic text
|
| 69 |
+
|
| 70 |
+
GOOD:
|
| 71 |
+
Policy validation engine verifies coverage
|
| 72 |
+
|
| 73 |
+
GOOD:
|
| 74 |
+
Smart approval routing triggers manager review
|
| 75 |
+
|
| 76 |
+
GOOD:
|
| 77 |
+
CRM sync service updates customer records
|
| 78 |
+
|
| 79 |
+
BAD:
|
| 80 |
+
The system automatically checks whether the policy
|
| 81 |
+
is valid and then sends it for manager approval
|
| 82 |
+
|
| 83 |
+
BAD:
|
| 84 |
+
This process improves efficiency and reduces manual effort
|
| 85 |
+
|
| 86 |
+
BAD:
|
| 87 |
+
The workflow becomes faster and more scalable
|
| 88 |
+
|
| 89 |
+
--------------------------------------------------
|
| 90 |
+
RULES
|
| 91 |
+
--------------------------------------------------
|
| 92 |
+
|
| 93 |
+
1. Keep BEFORE workflow realistic and messy
|
| 94 |
+
|
| 95 |
+
Examples:
|
| 96 |
+
|
| 97 |
+
- Agent opens email manually
|
| 98 |
+
- HR reviews resumes manually
|
| 99 |
+
- Finance validates invoice manually
|
| 100 |
+
|
| 101 |
+
2. AFTER workflow must be production-grade
|
| 102 |
+
|
| 103 |
+
Examples:
|
| 104 |
+
|
| 105 |
+
- Resume intake API ingests candidate profiles
|
| 106 |
+
- Skill matching engine scores JD fit
|
| 107 |
+
- Auto shortlist / reject / escalate
|
| 108 |
+
|
| 109 |
+
3. Include human review only where truly necessary
|
| 110 |
+
|
| 111 |
+
4. Prefer:
|
| 112 |
+
|
| 113 |
+
validation engine,
|
| 114 |
+
routing service,
|
| 115 |
+
approval workflow,
|
| 116 |
+
decision engine,
|
| 117 |
+
notification service,
|
| 118 |
+
CRM update,
|
| 119 |
+
ERP sync,
|
| 120 |
+
queue processing,
|
| 121 |
+
human escalation,
|
| 122 |
+
audit trail
|
| 123 |
+
|
| 124 |
+
5. Do NOT generate generic AI buzzwords
|
| 125 |
+
|
| 126 |
+
Avoid:
|
| 127 |
+
|
| 128 |
+
- AI powered solution
|
| 129 |
+
- smart automation platform
|
| 130 |
+
- intelligent system
|
| 131 |
+
- scalable transformation
|
| 132 |
+
|
| 133 |
+
Use real execution systems instead.
|
| 134 |
+
|
| 135 |
+
--------------------------------------------------
|
| 136 |
+
OUTPUT FORMAT
|
| 137 |
+
--------------------------------------------------
|
| 138 |
+
|
| 139 |
+
Return JSON only.
|
| 140 |
+
|
| 141 |
+
{
|
| 142 |
+
"before": [
|
| 143 |
+
"step 1",
|
| 144 |
+
"step 2",
|
| 145 |
+
"step 3"
|
| 146 |
+
],
|
| 147 |
+
"after": [
|
| 148 |
+
"step 1",
|
| 149 |
+
"step 2",
|
| 150 |
+
"step 3"
|
| 151 |
+
]
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
No markdown.
|
| 155 |
+
No explanation.
|
| 156 |
+
No commentary.
|
| 157 |
+
JSON only.
|
| 158 |
+
"""
|
src/state/state.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic import BaseModel, Field
|
| 2 |
+
from typing import List, Dict, Any
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class SystemState(BaseModel):
|
| 6 |
+
project_idea: str
|
| 7 |
+
workflow_steps: List[str] = Field(default_factory=list)
|
| 8 |
+
architecture_plan: Dict[str, Any] = Field(default_factory=dict)
|
| 9 |
+
critic_flags: List[str] = Field(default_factory=list)
|
| 10 |
+
refined_solution: Dict[str, Any] = Field(default_factory=dict)
|
| 11 |
+
critic_feedback: Dict[str, Any] = Field(default_factory=dict)
|
| 12 |
+
executive_summary: Dict[str, Any] = Field(default_factory=dict)
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
# Simple global in-memory state
|
| 16 |
+
system_state: SystemState = SystemState(
|
| 17 |
+
project_idea="",
|
| 18 |
+
workflow_steps=[],
|
| 19 |
+
architecture_plan={},
|
| 20 |
+
critic_flags=[],
|
| 21 |
+
refined_solution={},
|
| 22 |
+
critic_feedback={},
|
| 23 |
+
executive_summary={}
|
| 24 |
+
)
|
src/tools/json_parser.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
import re
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def safe_json_parse(raw_text, fallback):
|
| 6 |
+
"""
|
| 7 |
+
Safely parse LLM JSON output.
|
| 8 |
+
|
| 9 |
+
Handles:
|
| 10 |
+
- markdown code blocks
|
| 11 |
+
- extra explanation text
|
| 12 |
+
- malformed formatting
|
| 13 |
+
- greedy JSON extraction issues
|
| 14 |
+
- invalid output fallback
|
| 15 |
+
"""
|
| 16 |
+
|
| 17 |
+
try:
|
| 18 |
+
if not raw_text:
|
| 19 |
+
return fallback
|
| 20 |
+
|
| 21 |
+
cleaned = raw_text.strip()
|
| 22 |
+
|
| 23 |
+
# Remove markdown code fences
|
| 24 |
+
cleaned = re.sub(
|
| 25 |
+
r"```json|```python|```",
|
| 26 |
+
"",
|
| 27 |
+
cleaned
|
| 28 |
+
).strip()
|
| 29 |
+
|
| 30 |
+
# Normalize smart quotes
|
| 31 |
+
cleaned = cleaned.replace("β", '"')
|
| 32 |
+
cleaned = cleaned.replace("β", '"')
|
| 33 |
+
cleaned = cleaned.replace("β", "'")
|
| 34 |
+
|
| 35 |
+
# Extract first valid JSON object only (non-greedy)
|
| 36 |
+
match = re.search(
|
| 37 |
+
r"\{[\s\S]*?\}",
|
| 38 |
+
cleaned
|
| 39 |
+
)
|
| 40 |
+
|
| 41 |
+
if match:
|
| 42 |
+
cleaned = match.group()
|
| 43 |
+
|
| 44 |
+
return json.loads(cleaned)
|
| 45 |
+
|
| 46 |
+
except Exception as e:
|
| 47 |
+
print(f"JSON Parse Failed: {str(e)}")
|
| 48 |
+
return fallback
|
src/tools/llm.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from dotenv import load_dotenv
|
| 3 |
+
|
| 4 |
+
from langchain_groq import ChatGroq
|
| 5 |
+
from langchain_openai import ChatOpenAI
|
| 6 |
+
|
| 7 |
+
load_dotenv()
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def get_llm():
|
| 11 |
+
"""
|
| 12 |
+
Dynamic LLM Provider
|
| 13 |
+
|
| 14 |
+
DEV MODE:
|
| 15 |
+
Groq API
|
| 16 |
+
|
| 17 |
+
PROD MODE:
|
| 18 |
+
AMD MI300X + vLLM + Qwen2.5-7B-Instruct
|
| 19 |
+
"""
|
| 20 |
+
|
| 21 |
+
provider = os.getenv(
|
| 22 |
+
"LLM_PROVIDER",
|
| 23 |
+
"groq"
|
| 24 |
+
).lower()
|
| 25 |
+
|
| 26 |
+
# =========================
|
| 27 |
+
# AMD GPU Inference (PROD)
|
| 28 |
+
# =========================
|
| 29 |
+
if provider == "amd":
|
| 30 |
+
return ChatOpenAI(
|
| 31 |
+
api_key="dummy",
|
| 32 |
+
base_url=os.getenv(
|
| 33 |
+
"AMD_BASE_URL",
|
| 34 |
+
"http://129.212.182.205:8000/v1"
|
| 35 |
+
),
|
| 36 |
+
model=os.getenv(
|
| 37 |
+
"AMD_MODEL",
|
| 38 |
+
"Qwen/Qwen2.5-7B-Instruct"
|
| 39 |
+
),
|
| 40 |
+
temperature=0.1,
|
| 41 |
+
max_tokens=1200,
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
# =========================
|
| 45 |
+
# GROQ (DEV)
|
| 46 |
+
# =========================
|
| 47 |
+
return ChatGroq(
|
| 48 |
+
groq_api_key=os.getenv(
|
| 49 |
+
"GROQ_API_KEY"
|
| 50 |
+
),
|
| 51 |
+
model_name="llama-3.1-8b-instant",
|
| 52 |
+
temperature=0.1,
|
| 53 |
+
max_tokens=1200,
|
| 54 |
+
)
|
src/workflows/crew.py
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from src.agents.architect import architect_agent
|
| 2 |
+
from src.agents.critic import infrastructure_critic_agent
|
| 3 |
+
from src.agents.refiner import refiner_agent
|
| 4 |
+
from src.agents.executive_summary import executive_summary_agent
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
def run_systemforge(workflow_steps):
|
| 8 |
+
"""
|
| 9 |
+
workflow_steps:
|
| 10 |
+
[
|
| 11 |
+
"Resume comes from LinkedIn",
|
| 12 |
+
"HR manually shortlists candidates",
|
| 13 |
+
...
|
| 14 |
+
]
|
| 15 |
+
"""
|
| 16 |
+
|
| 17 |
+
# -----------------------------------
|
| 18 |
+
# STEP 1 β Architecture Generation
|
| 19 |
+
# -----------------------------------
|
| 20 |
+
|
| 21 |
+
architect_output = architect_agent(
|
| 22 |
+
workflow_steps=workflow_steps,
|
| 23 |
+
bottlenecks=None
|
| 24 |
+
)
|
| 25 |
+
|
| 26 |
+
# Safety fallback
|
| 27 |
+
after_workflow = architect_output.get(
|
| 28 |
+
"after_workflow",
|
| 29 |
+
[
|
| 30 |
+
"Workflow intake service captures requests",
|
| 31 |
+
"Validation engine verifies business rules",
|
| 32 |
+
"Queue orchestration handles async processing",
|
| 33 |
+
"Approval workflow triggers escalation routing",
|
| 34 |
+
"Observability layer tracks failures and audits"
|
| 35 |
+
]
|
| 36 |
+
)
|
| 37 |
+
|
| 38 |
+
architect_decisions = architect_output.get(
|
| 39 |
+
"decisions",
|
| 40 |
+
[
|
| 41 |
+
"Introduced queue-first workflow architecture",
|
| 42 |
+
"Separated validation from execution boundaries",
|
| 43 |
+
"Added policy engine for approval workflows",
|
| 44 |
+
"Created human escalation path for exceptions",
|
| 45 |
+
"Improved monitoring with audit-safe observability"
|
| 46 |
+
]
|
| 47 |
+
)
|
| 48 |
+
|
| 49 |
+
# -----------------------------------
|
| 50 |
+
# STEP 2 β Infrastructure Critic
|
| 51 |
+
# -----------------------------------
|
| 52 |
+
|
| 53 |
+
critic_output = infrastructure_critic_agent(
|
| 54 |
+
workflow_steps=workflow_steps,
|
| 55 |
+
architecture=architect_output
|
| 56 |
+
)
|
| 57 |
+
|
| 58 |
+
critic_risks = critic_output.get(
|
| 59 |
+
"risks",
|
| 60 |
+
[
|
| 61 |
+
"Approval queue lacks dead-letter handling",
|
| 62 |
+
"Missing retry-safe execution may duplicate actions",
|
| 63 |
+
"Manual escalation path creates bottlenecks",
|
| 64 |
+
"No centralized audit trail creates compliance risk",
|
| 65 |
+
"Missing monitoring hides production degradation"
|
| 66 |
+
]
|
| 67 |
+
)
|
| 68 |
+
|
| 69 |
+
# -----------------------------------
|
| 70 |
+
# STEP 3 β Production Refinement
|
| 71 |
+
# -----------------------------------
|
| 72 |
+
|
| 73 |
+
refiner_output = refiner_agent(
|
| 74 |
+
workflow_steps=workflow_steps,
|
| 75 |
+
architecture=architect_output,
|
| 76 |
+
critic_feedback=critic_output
|
| 77 |
+
)
|
| 78 |
+
|
| 79 |
+
refiner_improvements = refiner_output.get(
|
| 80 |
+
"improvements",
|
| 81 |
+
[
|
| 82 |
+
"Added dead-letter queue for failed approvals",
|
| 83 |
+
"Introduced idempotent retry-safe execution",
|
| 84 |
+
"Enabled audit-safe decision logging",
|
| 85 |
+
"Added rollback workflow for critical failures",
|
| 86 |
+
"Improved monitoring with human override paths"
|
| 87 |
+
]
|
| 88 |
+
)
|
| 89 |
+
|
| 90 |
+
architecture_layers = refiner_output.get(
|
| 91 |
+
"architecture_layers",
|
| 92 |
+
[]
|
| 93 |
+
)
|
| 94 |
+
|
| 95 |
+
# -----------------------------------
|
| 96 |
+
# STEP 4 β Executive Summary
|
| 97 |
+
# -----------------------------------
|
| 98 |
+
|
| 99 |
+
summary_output = executive_summary_agent(
|
| 100 |
+
workflow_steps=workflow_steps,
|
| 101 |
+
final_architecture=refiner_output
|
| 102 |
+
)
|
| 103 |
+
|
| 104 |
+
# -----------------------------------
|
| 105 |
+
# FINAL RESPONSE
|
| 106 |
+
# -----------------------------------
|
| 107 |
+
|
| 108 |
+
final_response = {
|
| 109 |
+
"workflowTransformation": {
|
| 110 |
+
"before": workflow_steps,
|
| 111 |
+
|
| 112 |
+
# VERY IMPORTANT:
|
| 113 |
+
# keep AFTER workflow short, clean,
|
| 114 |
+
# production-grade labels only
|
| 115 |
+
"after": after_workflow
|
| 116 |
+
},
|
| 117 |
+
|
| 118 |
+
"architect": {
|
| 119 |
+
"title": "SYSTEMS ARCHITECT",
|
| 120 |
+
"subtitle": "Production Architecture Design",
|
| 121 |
+
"decisions": architect_decisions
|
| 122 |
+
},
|
| 123 |
+
|
| 124 |
+
"critic": {
|
| 125 |
+
"title": "INFRASTRUCTURE CRITIC",
|
| 126 |
+
"subtitle": "Failure Points + Risk Detection",
|
| 127 |
+
"decisions": critic_risks
|
| 128 |
+
},
|
| 129 |
+
|
| 130 |
+
"refiner": {
|
| 131 |
+
"title": "PRODUCTION REFINER",
|
| 132 |
+
"subtitle": "Optimization + Reliability Improvements",
|
| 133 |
+
"decisions": refiner_improvements
|
| 134 |
+
},
|
| 135 |
+
|
| 136 |
+
"architectureLayers": architecture_layers,
|
| 137 |
+
|
| 138 |
+
# IMPORTANT:
|
| 139 |
+
# remove cost anxiety focus
|
| 140 |
+
# prioritize operational value
|
| 141 |
+
"finalMetrics": {
|
| 142 |
+
"deploymentReadiness":
|
| 143 |
+
summary_output.get(
|
| 144 |
+
"deployment_readiness",
|
| 145 |
+
"92%"
|
| 146 |
+
),
|
| 147 |
+
|
| 148 |
+
"automationPotential":
|
| 149 |
+
summary_output.get(
|
| 150 |
+
"automation_potential",
|
| 151 |
+
"88%"
|
| 152 |
+
),
|
| 153 |
+
|
| 154 |
+
"riskScore":
|
| 155 |
+
summary_output.get(
|
| 156 |
+
"risk_score",
|
| 157 |
+
"Low"
|
| 158 |
+
),
|
| 159 |
+
|
| 160 |
+
# Better than infra-cost obsession
|
| 161 |
+
"timeReduction":
|
| 162 |
+
"45β60 min β 10β15 min",
|
| 163 |
+
|
| 164 |
+
"architectureConfidence":
|
| 165 |
+
summary_output.get(
|
| 166 |
+
"confidence_score",
|
| 167 |
+
"High"
|
| 168 |
+
)
|
| 169 |
+
},
|
| 170 |
+
|
| 171 |
+
"executiveSummary": {
|
| 172 |
+
"title": "EXECUTIVE IMPACT",
|
| 173 |
+
"subtitle": "Business Outcome + ROI",
|
| 174 |
+
"decisions":
|
| 175 |
+
summary_output.get(
|
| 176 |
+
"business_impact",
|
| 177 |
+
[
|
| 178 |
+
"Reduced manual approvals significantly",
|
| 179 |
+
"Improved operational speed and reliability",
|
| 180 |
+
"Enabled production-grade deployment path"
|
| 181 |
+
]
|
| 182 |
+
)
|
| 183 |
+
}
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
return final_response
|