genoma-evolution 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.brv/.obsidian/app.json +1 -0
- package/.brv/.obsidian/appearance.json +1 -0
- package/.brv/.obsidian/core-plugins.json +33 -0
- package/.brv/.obsidian/graph.json +22 -0
- package/.brv/.obsidian/workspace.json +195 -0
- package/.brv/Sin ti/314/201tulo 1.canvas" +1 -0
- package/.brv/Sin ti/314/201tulo 2.canvas" +1 -0
- package/.brv/Sin ti/314/201tulo.canvas" +1 -0
- package/.brv/_queue_status.json +1 -0
- package/.brv/config.json +5 -0
- package/.brv/context-tree/_index.md +60 -0
- package/.brv/context-tree/_manifest.json +165 -0
- package/.brv/context-tree/backend/_index.md +24 -0
- package/.brv/context-tree/backend/backend/_index.md +40 -0
- package/.brv/context-tree/backend/backend/init.abstract.md +0 -0
- package/.brv/context-tree/backend/backend/init.md +27 -0
- package/.brv/context-tree/backend/backend/init.overview.md +29 -0
- package/.brv/context-tree/backend/backend/job_tracker.abstract.md +1 -0
- package/.brv/context-tree/backend/backend/job_tracker.md +273 -0
- package/.brv/context-tree/backend/backend/job_tracker.overview.md +31 -0
- package/.brv/context-tree/backend/backend/main.abstract.md +0 -0
- package/.brv/context-tree/backend/backend/main.md +1292 -0
- package/.brv/context-tree/backend/backend/main.overview.md +30 -0
- package/.brv/context-tree/backend/backend/requirements.abstract.md +1 -0
- package/.brv/context-tree/backend/backend/requirements.md +37 -0
- package/.brv/context-tree/backend/backend/requirements.overview.md +28 -0
- package/.brv/context-tree/docs/_index.md +37 -0
- package/.brv/context-tree/docs/api/_index.md +54 -0
- package/.brv/context-tree/docs/api/context.md +11 -0
- package/.brv/context-tree/docs/api/hermes_api_openapi_specification.abstract.md +0 -0
- package/.brv/context-tree/docs/api/hermes_api_openapi_specification.md +468 -0
- package/.brv/context-tree/docs/api/hermes_api_openapi_specification.overview.md +44 -0
- package/.brv/context-tree/frontend/_index.md +48 -0
- package/.brv/context-tree/frontend/hermes_dashboard/_index.md +31 -0
- package/.brv/context-tree/frontend/hermes_dashboard/architecture_overview.abstract.md +0 -0
- package/.brv/context-tree/frontend/hermes_dashboard/architecture_overview.md +41 -0
- package/.brv/context-tree/frontend/hermes_dashboard/architecture_overview.overview.md +34 -0
- package/.brv/context-tree/frontend/src/_index.md +53 -0
- package/.brv/context-tree/frontend/src/components/_index.md +52 -0
- package/.brv/context-tree/frontend/src/components/sidebar_navigation_component.abstract.md +0 -0
- package/.brv/context-tree/frontend/src/components/sidebar_navigation_component.md +161 -0
- package/.brv/context-tree/frontend/src/components/sidebar_navigation_component.overview.md +32 -0
- package/.brv/context-tree/frontend/src/context.md +10 -0
- package/.brv/context-tree/frontend/src/functioncallingpage.abstract.md +0 -0
- package/.brv/context-tree/frontend/src/functioncallingpage.md +34 -0
- package/.brv/context-tree/frontend/src/functioncallingpage.overview.md +26 -0
- package/.brv/context-tree/frontend/src/lib/_index.md +48 -0
- package/.brv/context-tree/frontend/src/lib/api_client_library.abstract.md +1 -0
- package/.brv/context-tree/frontend/src/lib/api_client_library.md +403 -0
- package/.brv/context-tree/frontend/src/lib/api_client_library.overview.md +69 -0
- package/.brv/context-tree/frontend/src/page.abstract.md +0 -0
- package/.brv/context-tree/frontend/src/page.md +103 -0
- package/.brv/context-tree/frontend/src/page.overview.md +7 -0
- package/.brv/context-tree/frontend/src/settingspage.abstract.md +0 -0
- package/.brv/context-tree/frontend/src/settingspage.md +124 -0
- package/.brv/context-tree/frontend/src/settingspage.overview.md +34 -0
- package/.brv/context-tree/frontend/src/sidebar.abstract.md +0 -0
- package/.brv/context-tree/frontend/src/sidebar.md +170 -0
- package/.brv/context-tree/frontend/src/sidebar.overview.md +25 -0
- package/.brv/context-tree/meta/_index.md +24 -0
- package/.brv/context-tree/meta/curation_context/_index.md +24 -0
- package/.brv/context-tree/meta/curation_context/empty_context.abstract.md +4 -0
- package/.brv/context-tree/meta/curation_context/empty_context.md +35 -0
- package/.brv/context-tree/meta/curation_context/empty_context.overview.md +20 -0
- package/.brv/dream-log/drm-1777341062653.json +33 -0
- package/.brv/dream-state.json +8 -0
- package/.brv/dream.lock +0 -0
- package/.brv/review-backups/docs/api/hermes_api_openapi_specification.md +468 -0
- package/.claude/settings.local.json +7 -0
- package/.claude/worktrees/phase-2-mcp/.brv/.obsidian/app.json +1 -0
- package/.claude/worktrees/phase-2-mcp/.brv/.obsidian/appearance.json +1 -0
- package/.claude/worktrees/phase-2-mcp/.brv/.obsidian/core-plugins.json +33 -0
- package/.claude/worktrees/phase-2-mcp/.brv/.obsidian/graph.json +22 -0
- package/.claude/worktrees/phase-2-mcp/.brv/.obsidian/workspace.json +195 -0
- package/.claude/worktrees/phase-2-mcp/.brv/Sin t/303/255tulo 1.canvas" +1 -0
- package/.claude/worktrees/phase-2-mcp/.brv/Sin t/303/255tulo 2.canvas" +1 -0
- package/.claude/worktrees/phase-2-mcp/.brv/Sin t/303/255tulo.canvas" +1 -0
- package/.claude/worktrees/phase-2-mcp/.brv/_queue_status.json +1 -0
- package/.claude/worktrees/phase-2-mcp/.brv/config.json +5 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/_index.md +60 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/_manifest.json +165 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/_index.md +24 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/_index.md +40 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/init.abstract.md +0 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/init.md +27 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/init.overview.md +29 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/job_tracker.abstract.md +1 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/job_tracker.md +273 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/job_tracker.overview.md +31 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/main.abstract.md +0 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/main.md +1292 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/main.overview.md +30 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/requirements.abstract.md +1 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/requirements.md +37 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/requirements.overview.md +28 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/docs/_index.md +37 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/docs/api/_index.md +54 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/docs/api/context.md +11 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/docs/api/hermes_api_openapi_specification.abstract.md +0 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/docs/api/hermes_api_openapi_specification.md +468 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/docs/api/hermes_api_openapi_specification.overview.md +44 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/_index.md +48 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/hermes_dashboard/_index.md +31 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/hermes_dashboard/architecture_overview.abstract.md +0 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/hermes_dashboard/architecture_overview.md +41 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/hermes_dashboard/architecture_overview.overview.md +34 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/_index.md +53 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/components/_index.md +52 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/components/sidebar_navigation_component.abstract.md +0 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/components/sidebar_navigation_component.md +161 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/components/sidebar_navigation_component.overview.md +32 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/context.md +10 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/functioncallingpage.abstract.md +0 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/functioncallingpage.md +34 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/functioncallingpage.overview.md +26 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/lib/_index.md +48 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/lib/api_client_library.abstract.md +1 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/lib/api_client_library.md +403 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/lib/api_client_library.overview.md +69 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/page.abstract.md +0 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/page.md +103 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/page.overview.md +7 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/settingspage.abstract.md +0 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/settingspage.md +124 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/settingspage.overview.md +34 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/sidebar.abstract.md +0 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/sidebar.md +170 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/sidebar.overview.md +25 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/meta/_index.md +24 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/meta/curation_context/_index.md +24 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/meta/curation_context/empty_context.abstract.md +4 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/meta/curation_context/empty_context.md +35 -0
- package/.claude/worktrees/phase-2-mcp/.brv/context-tree/meta/curation_context/empty_context.overview.md +20 -0
- package/.claude/worktrees/phase-2-mcp/.brv/dream-log/drm-1777341062653.json +33 -0
- package/.claude/worktrees/phase-2-mcp/.brv/dream-state.json +8 -0
- package/.claude/worktrees/phase-2-mcp/.brv/dream.lock +0 -0
- package/.claude/worktrees/phase-2-mcp/.brv/review-backups/docs/api/hermes_api_openapi_specification.md +468 -0
- package/.claude/worktrees/phase-2-mcp/.claude/settings.local.json +13 -0
- package/.claude/worktrees/phase-2-mcp/.kilocode/package-lock.json +378 -0
- package/.claude/worktrees/phase-2-mcp/.kilocode/package.json +5 -0
- package/.claude/worktrees/phase-2-mcp/AGENTS.md +5 -0
- package/.claude/worktrees/phase-2-mcp/CLAUDE.md +29 -0
- package/.claude/worktrees/phase-2-mcp/QA_AUDIT_PLAN.md +156 -0
- package/.claude/worktrees/phase-2-mcp/README.md +316 -0
- package/.claude/worktrees/phase-2-mcp/agent-agnostic-evolution-dashboard.md +405 -0
- package/.claude/worktrees/phase-2-mcp/backend/__init__.py +0 -0
- package/.claude/worktrees/phase-2-mcp/backend/collectors/__init__.py +0 -0
- package/.claude/worktrees/phase-2-mcp/backend/collectors/claude_code_collector.py +277 -0
- package/.claude/worktrees/phase-2-mcp/backend/collectors/hermes_collector.py +68 -0
- package/.claude/worktrees/phase-2-mcp/backend/curator.py +512 -0
- package/.claude/worktrees/phase-2-mcp/backend/eval/__init__.py +19 -0
- package/.claude/worktrees/phase-2-mcp/backend/eval/engine.py +116 -0
- package/.claude/worktrees/phase-2-mcp/backend/eval/scorers.py +201 -0
- package/.claude/worktrees/phase-2-mcp/backend/generate_dataset.py +86 -0
- package/.claude/worktrees/phase-2-mcp/backend/job_tracker.py +232 -0
- package/.claude/worktrees/phase-2-mcp/backend/main.py +1746 -0
- package/.claude/worktrees/phase-2-mcp/backend/mcp_server.py +250 -0
- package/.claude/worktrees/phase-2-mcp/backend/promethean/__init__.py +24 -0
- package/.claude/worktrees/phase-2-mcp/backend/promethean/cycle_orchestrator.py +270 -0
- package/.claude/worktrees/phase-2-mcp/backend/promethean/delta_validator.py +191 -0
- package/.claude/worktrees/phase-2-mcp/backend/promethean/dspy_compiler.py +315 -0
- package/.claude/worktrees/phase-2-mcp/backend/promethean/gepa_strategist.py +213 -0
- package/.claude/worktrees/phase-2-mcp/backend/promethean/models.py +260 -0
- package/.claude/worktrees/phase-2-mcp/backend/promethean/skill_deployer.py +195 -0
- package/.claude/worktrees/phase-2-mcp/backend/promethean/trace_ingestion.py +142 -0
- package/.claude/worktrees/phase-2-mcp/backend/requirements.txt +6 -0
- package/.claude/worktrees/phase-2-mcp/backend/sdd_evolve.py +459 -0
- package/.claude/worktrees/phase-2-mcp/backend/skill_detector.py +227 -0
- package/.claude/worktrees/phase-2-mcp/backend/skill_registry.py +289 -0
- package/.claude/worktrees/phase-2-mcp/backend/storage/__init__.py +5 -0
- package/.claude/worktrees/phase-2-mcp/backend/storage/run_store.py +393 -0
- package/.claude/worktrees/phase-2-mcp/backend/storage/schema.sql +99 -0
- package/.claude/worktrees/phase-2-mcp/backend/validate_evolution.py +267 -0
- package/.claude/worktrees/phase-2-mcp/components.json +28 -0
- package/.claude/worktrees/phase-2-mcp/docs/api/hermes-api.openapi.yaml +438 -0
- package/.claude/worktrees/phase-2-mcp/docs/hero.svg +148 -0
- package/.claude/worktrees/phase-2-mcp/eslint.config.mjs +18 -0
- package/.claude/worktrees/phase-2-mcp/install.sh +245 -0
- package/.claude/worktrees/phase-2-mcp/next-env.d.ts +6 -0
- package/.claude/worktrees/phase-2-mcp/next.config.ts +32 -0
- package/.claude/worktrees/phase-2-mcp/package-lock.json +11936 -0
- package/.claude/worktrees/phase-2-mcp/package.json +41 -0
- package/.claude/worktrees/phase-2-mcp/pnpm-workspace.yaml +4 -0
- package/.claude/worktrees/phase-2-mcp/postcss.config.mjs +7 -0
- package/.claude/worktrees/phase-2-mcp/public/file.svg +1 -0
- package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Display-Bold.otf +0 -0
- package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Display-Heavy.otf +0 -0
- package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Display-Medium.otf +0 -0
- package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Display-Regular.otf +0 -0
- package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Display-Semibold.otf +0 -0
- package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Text-Bold.otf +0 -0
- package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Text-Heavy.otf +0 -0
- package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Text-Medium.otf +0 -0
- package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Text-Regular.otf +0 -0
- package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Text-Semibold.otf +0 -0
- package/.claude/worktrees/phase-2-mcp/public/globe.svg +1 -0
- package/.claude/worktrees/phase-2-mcp/public/next.svg +1 -0
- package/.claude/worktrees/phase-2-mcp/public/theme-preview.html +257 -0
- package/.claude/worktrees/phase-2-mcp/public/vercel.svg +1 -0
- package/.claude/worktrees/phase-2-mcp/public/window.svg +1 -0
- package/.claude/worktrees/phase-2-mcp/run.sh +26 -0
- package/.claude/worktrees/phase-2-mcp/skills-lock.json +10 -0
- package/.claude/worktrees/phase-2-mcp/specs/event-schema.md +223 -0
- package/.claude/worktrees/phase-2-mcp/specs/examples/run.jsonl +3 -0
- package/.claude/worktrees/phase-2-mcp/src/app/api/[...path]/route.ts +55 -0
- package/.claude/worktrees/phase-2-mcp/src/app/api/auth/token/route.ts +22 -0
- package/.claude/worktrees/phase-2-mcp/src/app/evolution/page.tsx +589 -0
- package/.claude/worktrees/phase-2-mcp/src/app/favicon.ico +0 -0
- package/.claude/worktrees/phase-2-mcp/src/app/globals.css +321 -0
- package/.claude/worktrees/phase-2-mcp/src/app/layout.tsx +63 -0
- package/.claude/worktrees/phase-2-mcp/src/app/page.tsx +70 -0
- package/.claude/worktrees/phase-2-mcp/src/app/skills/page.tsx +369 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ApiConfigCard.tsx +199 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ColorBends.css +1 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ColorBends.d.ts +1 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ColorBends.jsx +1 -0
- package/.claude/worktrees/phase-2-mcp/src/components/CoreLoopToggle.tsx +111 -0
- package/.claude/worktrees/phase-2-mcp/src/components/EnvironmentStatus.tsx +176 -0
- package/.claude/worktrees/phase-2-mcp/src/components/EvolutionBackground.tsx +1 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ReactQueryProvider.tsx +24 -0
- package/.claude/worktrees/phase-2-mcp/src/components/Sidebar.tsx +247 -0
- package/.claude/worktrees/phase-2-mcp/src/components/SkillDiffViewer.tsx +154 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ThemeAwareBackground.tsx +67 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ThemeToggle.tsx +54 -0
- package/.claude/worktrees/phase-2-mcp/src/components/WelcomeHero.tsx +77 -0
- package/.claude/worktrees/phase-2-mcp/src/components/bits/ClickSpark.tsx +116 -0
- package/.claude/worktrees/phase-2-mcp/src/components/bits/CountUp.tsx +98 -0
- package/.claude/worktrees/phase-2-mcp/src/components/bits/DarkSelect.tsx +95 -0
- package/.claude/worktrees/phase-2-mcp/src/components/bits/DecryptedText.tsx +161 -0
- package/.claude/worktrees/phase-2-mcp/src/components/bits/ElectricBorder.tsx +184 -0
- package/.claude/worktrees/phase-2-mcp/src/components/bits/GlitchText.tsx +34 -0
- package/.claude/worktrees/phase-2-mcp/src/components/bits/ShinyText.tsx +55 -0
- package/.claude/worktrees/phase-2-mcp/src/components/bits/SpotlightCard.tsx +42 -0
- package/.claude/worktrees/phase-2-mcp/src/components/bits/TextType.tsx +95 -0
- package/.claude/worktrees/phase-2-mcp/src/components/bits/index.ts +9 -0
- package/.claude/worktrees/phase-2-mcp/src/components/pages/CuratorPage.tsx +632 -0
- package/.claude/worktrees/phase-2-mcp/src/components/pages/DatasetPage.tsx +271 -0
- package/.claude/worktrees/phase-2-mcp/src/components/pages/EvolutionPage.tsx +676 -0
- package/.claude/worktrees/phase-2-mcp/src/components/pages/FunctionCallingPage.tsx +1 -0
- package/.claude/worktrees/phase-2-mcp/src/components/pages/LogsPage.tsx +272 -0
- package/.claude/worktrees/phase-2-mcp/src/components/pages/MetricsPage.tsx +246 -0
- package/.claude/worktrees/phase-2-mcp/src/components/pages/OverviewPage.tsx +420 -0
- package/.claude/worktrees/phase-2-mcp/src/components/pages/SettingsPage.tsx +88 -0
- package/.claude/worktrees/phase-2-mcp/src/components/pages/SkillStudioPage.tsx +376 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ui/animated-theme-toggler.tsx +97 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ui/button.tsx +67 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ui/card.tsx +103 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ui/input.tsx +19 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ui/separator.tsx +28 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ui/sheet.tsx +147 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ui/sidebar.tsx +702 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ui/skeleton.tsx +13 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ui/theme-toggle.tsx +272 -0
- package/.claude/worktrees/phase-2-mcp/src/components/ui/tooltip.tsx +57 -0
- package/.claude/worktrees/phase-2-mcp/src/hooks/use-mobile.ts +19 -0
- package/.claude/worktrees/phase-2-mcp/src/lib/api.ts +455 -0
- package/.claude/worktrees/phase-2-mcp/src/lib/queryClient.ts +12 -0
- package/.claude/worktrees/phase-2-mcp/src/lib/utils.ts +6 -0
- package/.claude/worktrees/phase-2-mcp/stitch/agent_dashboard/DESIGN_SPEC.md +521 -0
- package/.claude/worktrees/phase-2-mcp/stitch/agent_dashboard/prototype.html +676 -0
- package/.claude/worktrees/phase-2-mcp/stitch/curator_workspace/code.html +448 -0
- package/.claude/worktrees/phase-2-mcp/stitch/curator_workspace/screen.png +0 -0
- package/.claude/worktrees/phase-2-mcp/stitch/datasets/code.html +479 -0
- package/.claude/worktrees/phase-2-mcp/stitch/datasets/screen.png +0 -0
- package/.claude/worktrees/phase-2-mcp/stitch/evolution_history/code.html +461 -0
- package/.claude/worktrees/phase-2-mcp/stitch/evolution_history/screen.png +0 -0
- package/.claude/worktrees/phase-2-mcp/stitch/hermes_dashboard/DESIGN.md +192 -0
- package/.claude/worktrees/phase-2-mcp/stitch/hermes_dashboard/DESIGN_SPEC.md +455 -0
- package/.claude/worktrees/phase-2-mcp/stitch/hermes_overview/code.html +399 -0
- package/.claude/worktrees/phase-2-mcp/stitch/hermes_overview/screen.png +0 -0
- package/.claude/worktrees/phase-2-mcp/stitch/live_logs/code.html +324 -0
- package/.claude/worktrees/phase-2-mcp/stitch/live_logs/screen.png +0 -0
- package/.claude/worktrees/phase-2-mcp/stitch/skill_hub/code.html +596 -0
- package/.claude/worktrees/phase-2-mcp/stitch/skill_hub/screen.png +0 -0
- package/.claude/worktrees/phase-2-mcp/stitch/system_metrics/code.html +527 -0
- package/.claude/worktrees/phase-2-mcp/stitch/system_metrics/screen.png +0 -0
- package/.claude/worktrees/phase-2-mcp/stitch/system_settings/code.html +257 -0
- package/.claude/worktrees/phase-2-mcp/stitch/system_settings/screen.png +0 -0
- package/.claude/worktrees/phase-2-mcp/test_dashboard.py +201 -0
- package/.claude/worktrees/phase-2-mcp/tests/collectors/__init__.py +0 -0
- package/.claude/worktrees/phase-2-mcp/tests/collectors/fixtures/sample_session.jsonl +7 -0
- package/.claude/worktrees/phase-2-mcp/tests/collectors/test_claude_code_collector.py +171 -0
- package/.claude/worktrees/phase-2-mcp/tests/collectors/test_hermes_collector.py +167 -0
- package/.claude/worktrees/phase-2-mcp/tests/eval/test_engine.py +234 -0
- package/.claude/worktrees/phase-2-mcp/tests/eval/test_scorers.py +249 -0
- package/.claude/worktrees/phase-2-mcp/tests/storage/__init__.py +0 -0
- package/.claude/worktrees/phase-2-mcp/tests/storage/test_run_store.py +359 -0
- package/.claude/worktrees/phase-2-mcp/tests/test_curator.py +559 -0
- package/.claude/worktrees/phase-2-mcp/tests/test_mcp_server.py +114 -0
- package/.claude/worktrees/phase-2-mcp/tsconfig.json +34 -0
- package/.env.example +72 -0
- package/.kilocode/package-lock.json +378 -0
- package/.kilocode/package.json +5 -0
- package/AGENTS.md +5 -0
- package/CLAUDE.md +29 -0
- package/QA_AUDIT_PLAN.md +156 -0
- package/README.md +355 -0
- package/agent-agnostic-evolution-dashboard.md +405 -0
- package/backend/__init__.py +0 -0
- package/backend/collectors/__init__.py +0 -0
- package/backend/collectors/claude_code_collector.py +277 -0
- package/backend/collectors/hermes_collector.py +68 -0
- package/backend/curator.py +512 -0
- package/backend/eval/__init__.py +19 -0
- package/backend/eval/engine.py +116 -0
- package/backend/eval/scorers.py +201 -0
- package/backend/generate_dataset.py +86 -0
- package/backend/job_tracker.py +232 -0
- package/backend/main.py +1746 -0
- package/backend/mcp_server.py +250 -0
- package/backend/promethean/__init__.py +24 -0
- package/backend/promethean/cycle_orchestrator.py +270 -0
- package/backend/promethean/delta_validator.py +191 -0
- package/backend/promethean/dspy_compiler.py +315 -0
- package/backend/promethean/gepa_strategist.py +213 -0
- package/backend/promethean/models.py +260 -0
- package/backend/promethean/skill_deployer.py +195 -0
- package/backend/promethean/trace_ingestion.py +142 -0
- package/backend/requirements.txt +6 -0
- package/backend/sdd_evolve.py +459 -0
- package/backend/skill_detector.py +227 -0
- package/backend/skill_registry.py +289 -0
- package/backend/storage/__init__.py +5 -0
- package/backend/storage/run_store.py +393 -0
- package/backend/storage/schema.sql +99 -0
- package/backend/validate_evolution.py +267 -0
- package/bin/genoma.js +250 -0
- package/components.json +28 -0
- package/docs/api/hermes-api.openapi.yaml +438 -0
- package/docs/hero.svg +148 -0
- package/eslint.config.mjs +18 -0
- package/install.sh +245 -0
- package/next-env.d.ts +6 -0
- package/next.config.ts +32 -0
- package/package.json +46 -0
- package/pnpm-workspace.yaml +4 -0
- package/postcss.config.mjs +7 -0
- package/public/file.svg +1 -0
- package/public/fonts/SF-Pro-Display-Bold.otf +0 -0
- package/public/fonts/SF-Pro-Display-Heavy.otf +0 -0
- package/public/fonts/SF-Pro-Display-Medium.otf +0 -0
- package/public/fonts/SF-Pro-Display-Regular.otf +0 -0
- package/public/fonts/SF-Pro-Display-Semibold.otf +0 -0
- package/public/fonts/SF-Pro-Text-Bold.otf +0 -0
- package/public/fonts/SF-Pro-Text-Heavy.otf +0 -0
- package/public/fonts/SF-Pro-Text-Medium.otf +0 -0
- package/public/fonts/SF-Pro-Text-Regular.otf +0 -0
- package/public/fonts/SF-Pro-Text-Semibold.otf +0 -0
- package/public/globe.svg +1 -0
- package/public/next.svg +1 -0
- package/public/theme-preview.html +257 -0
- package/public/vercel.svg +1 -0
- package/public/window.svg +1 -0
- package/run.sh +26 -0
- package/scripts/postinstall.js +50 -0
- package/skills-lock.json +10 -0
- package/specs/event-schema.md +223 -0
- package/specs/examples/run.jsonl +3 -0
- package/src/app/api/[...path]/route.ts +55 -0
- package/src/app/api/auth/token/route.ts +22 -0
- package/src/app/evolution/page.tsx +589 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/globals.css +321 -0
- package/src/app/layout.tsx +63 -0
- package/src/app/page.tsx +70 -0
- package/src/app/skills/page.tsx +369 -0
- package/src/components/ApiConfigCard.tsx +199 -0
- package/src/components/ColorBends.css +1 -0
- package/src/components/ColorBends.d.ts +1 -0
- package/src/components/ColorBends.jsx +1 -0
- package/src/components/CoreLoopToggle.tsx +111 -0
- package/src/components/EnvironmentStatus.tsx +176 -0
- package/src/components/EvolutionBackground.tsx +1 -0
- package/src/components/ReactQueryProvider.tsx +24 -0
- package/src/components/Sidebar.tsx +247 -0
- package/src/components/SkillDiffViewer.tsx +154 -0
- package/src/components/ThemeAwareBackground.tsx +67 -0
- package/src/components/ThemeToggle.tsx +54 -0
- package/src/components/WelcomeHero.tsx +77 -0
- package/src/components/bits/ClickSpark.tsx +116 -0
- package/src/components/bits/CountUp.tsx +98 -0
- package/src/components/bits/DarkSelect.tsx +95 -0
- package/src/components/bits/DecryptedText.tsx +161 -0
- package/src/components/bits/ElectricBorder.tsx +184 -0
- package/src/components/bits/GlitchText.tsx +34 -0
- package/src/components/bits/ShinyText.tsx +55 -0
- package/src/components/bits/SpotlightCard.tsx +42 -0
- package/src/components/bits/TextType.tsx +95 -0
- package/src/components/bits/index.ts +9 -0
- package/src/components/pages/CuratorPage.tsx +632 -0
- package/src/components/pages/DatasetPage.tsx +271 -0
- package/src/components/pages/EvolutionPage.tsx +676 -0
- package/src/components/pages/FunctionCallingPage.tsx +1 -0
- package/src/components/pages/LogsPage.tsx +272 -0
- package/src/components/pages/MetricsPage.tsx +246 -0
- package/src/components/pages/OverviewPage.tsx +420 -0
- package/src/components/pages/SettingsPage.tsx +88 -0
- package/src/components/pages/SkillStudioPage.tsx +376 -0
- package/src/components/ui/animated-theme-toggler.tsx +97 -0
- package/src/components/ui/button.tsx +67 -0
- package/src/components/ui/card.tsx +103 -0
- package/src/components/ui/input.tsx +19 -0
- package/src/components/ui/separator.tsx +28 -0
- package/src/components/ui/sheet.tsx +147 -0
- package/src/components/ui/sidebar.tsx +702 -0
- package/src/components/ui/skeleton.tsx +13 -0
- package/src/components/ui/theme-toggle.tsx +272 -0
- package/src/components/ui/tooltip.tsx +57 -0
- package/src/hooks/use-mobile.ts +19 -0
- package/src/lib/api.ts +455 -0
- package/src/lib/queryClient.ts +12 -0
- package/src/lib/utils.ts +6 -0
- package/stitch/agent_dashboard/DESIGN_SPEC.md +521 -0
- package/stitch/agent_dashboard/prototype.html +676 -0
- package/stitch/curator_workspace/code.html +448 -0
- package/stitch/curator_workspace/screen.png +0 -0
- package/stitch/datasets/code.html +479 -0
- package/stitch/datasets/screen.png +0 -0
- package/stitch/evolution_history/code.html +461 -0
- package/stitch/evolution_history/screen.png +0 -0
- package/stitch/hermes_dashboard/DESIGN.md +192 -0
- package/stitch/hermes_dashboard/DESIGN_SPEC.md +455 -0
- package/stitch/hermes_overview/code.html +399 -0
- package/stitch/hermes_overview/screen.png +0 -0
- package/stitch/live_logs/code.html +324 -0
- package/stitch/live_logs/screen.png +0 -0
- package/stitch/skill_hub/code.html +596 -0
- package/stitch/skill_hub/screen.png +0 -0
- package/stitch/system_metrics/code.html +527 -0
- package/stitch/system_metrics/screen.png +0 -0
- package/stitch/system_settings/code.html +257 -0
- package/stitch/system_settings/screen.png +0 -0
- package/test_dashboard.py +201 -0
- package/tests/collectors/__init__.py +0 -0
- package/tests/collectors/fixtures/sample_session.jsonl +7 -0
- package/tests/collectors/test_claude_code_collector.py +171 -0
- package/tests/collectors/test_hermes_collector.py +167 -0
- package/tests/eval/test_engine.py +234 -0
- package/tests/eval/test_scorers.py +249 -0
- package/tests/storage/__init__.py +0 -0
- package/tests/storage/test_run_store.py +359 -0
- package/tests/test_curator.py +559 -0
- package/tests/test_e2e_npm.py +621 -0
- package/tests/test_mcp_server.py +114 -0
- package/tsconfig.json +34 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { Sun, Moon } from "lucide-react";
|
|
5
|
+
|
|
6
|
+
export default function ThemeToggle() {
|
|
7
|
+
const [isDark, setIsDark] = useState(true);
|
|
8
|
+
const [mounted, setMounted] = useState(false);
|
|
9
|
+
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
setMounted(true);
|
|
12
|
+
const saved = localStorage.getItem("genoma-theme");
|
|
13
|
+
const prefersDark = saved ? saved === "dark" : true;
|
|
14
|
+
setIsDark(prefersDark);
|
|
15
|
+
if (prefersDark) {
|
|
16
|
+
document.documentElement.classList.add("dark");
|
|
17
|
+
} else {
|
|
18
|
+
document.documentElement.classList.remove("dark");
|
|
19
|
+
}
|
|
20
|
+
}, []);
|
|
21
|
+
|
|
22
|
+
const toggle = () => {
|
|
23
|
+
const next = !isDark;
|
|
24
|
+
setIsDark(next);
|
|
25
|
+
localStorage.setItem("genoma-theme", next ? "dark" : "light");
|
|
26
|
+
if (next) {
|
|
27
|
+
document.documentElement.classList.add("dark");
|
|
28
|
+
} else {
|
|
29
|
+
document.documentElement.classList.remove("dark");
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
if (!mounted) {
|
|
34
|
+
return (
|
|
35
|
+
<button className="w-9 h-9 rounded-lg flex items-center justify-center text-gray-400">
|
|
36
|
+
<Sun className="w-5 h-5" />
|
|
37
|
+
</button>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<button
|
|
43
|
+
onClick={toggle}
|
|
44
|
+
className={`w-9 h-9 rounded-lg flex items-center justify-center transition-all duration-200 ${
|
|
45
|
+
isDark
|
|
46
|
+
? "bg-gray-800 text-yellow-400 hover:bg-gray-700"
|
|
47
|
+
: "bg-white text-primary-600 shadow-[var(--evo-shadow-md)] border border-gray-200 hover:bg-[var(--evo-bg-surface-hover)]"
|
|
48
|
+
}`}
|
|
49
|
+
title={isDark ? "Cambiar a Light Mode" : "Cambiar a Dark Mode"}
|
|
50
|
+
>
|
|
51
|
+
{isDark ? <Moon className="w-5 h-5" /> : <Sun className="w-5 h-5" />}
|
|
52
|
+
</button>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { motion } from "framer-motion";
|
|
4
|
+
import { Sparkles, Dna } from "lucide-react";
|
|
5
|
+
|
|
6
|
+
export default function WelcomeHero() {
|
|
7
|
+
return (
|
|
8
|
+
<motion.section
|
|
9
|
+
initial={{ opacity: 0, y: 20 }}
|
|
10
|
+
animate={{ opacity: 1, y: 0 }}
|
|
11
|
+
transition={{ duration: 0.8, ease: [0.25, 0.46, 0.45, 0.94] }}
|
|
12
|
+
className="relative flex flex-col items-center justify-center py-20 px-4 overflow-hidden"
|
|
13
|
+
>
|
|
14
|
+
{/* Background orbs */}
|
|
15
|
+
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
|
16
|
+
<motion.div
|
|
17
|
+
animate={{ scale: [1, 1.2, 1], opacity: [0.08, 0.15, 0.08] }}
|
|
18
|
+
transition={{ duration: 6, repeat: Infinity, ease: "easeInOut" }}
|
|
19
|
+
className="absolute top-1/4 left-1/4 w-96 h-96 rounded-full"
|
|
20
|
+
style={{
|
|
21
|
+
background: "radial-gradient(circle, rgba(139,92,246,0.3) 0%, transparent 70%)",
|
|
22
|
+
}}
|
|
23
|
+
/>
|
|
24
|
+
<motion.div
|
|
25
|
+
animate={{ scale: [1.2, 1, 1.2], opacity: [0.08, 0.12, 0.08] }}
|
|
26
|
+
transition={{ duration: 8, repeat: Infinity, ease: "easeInOut", delay: 2 }}
|
|
27
|
+
className="absolute bottom-1/4 right-1/4 w-96 h-96 rounded-full"
|
|
28
|
+
style={{
|
|
29
|
+
background: "radial-gradient(circle, rgba(6,182,212,0.3) 0%, transparent 70%)",
|
|
30
|
+
}}
|
|
31
|
+
/>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
{/* Badge */}
|
|
35
|
+
<motion.div
|
|
36
|
+
initial={{ opacity: 0, scale: 0.9 }}
|
|
37
|
+
animate={{ opacity: 1, scale: 1 }}
|
|
38
|
+
transition={{ delay: 0.3, duration: 0.5 }}
|
|
39
|
+
className="flex items-center gap-2 px-4 py-1.5 rounded-full glass-card mb-6"
|
|
40
|
+
>
|
|
41
|
+
<Dna className="w-3.5 h-3.5 text-accent-violet" />
|
|
42
|
+
<span className="text-xs font-medium text-muted-foreground tracking-wide uppercase">
|
|
43
|
+
Autonomous Evolution Interface
|
|
44
|
+
</span>
|
|
45
|
+
<Sparkles className="w-3.5 h-3.5 text-accent-cyan" />
|
|
46
|
+
</motion.div>
|
|
47
|
+
|
|
48
|
+
{/* Title */}
|
|
49
|
+
<motion.h1
|
|
50
|
+
initial={{ opacity: 0, y: 10 }}
|
|
51
|
+
animate={{ opacity: 1, y: 0 }}
|
|
52
|
+
transition={{ delay: 0.5, duration: 0.8 }}
|
|
53
|
+
className="text-5xl md:text-7xl font-bold text-center leading-tight tracking-tight"
|
|
54
|
+
>
|
|
55
|
+
<span className="gradient-text">Genoma</span>
|
|
56
|
+
</motion.h1>
|
|
57
|
+
|
|
58
|
+
{/* Subtitle */}
|
|
59
|
+
<motion.p
|
|
60
|
+
initial={{ opacity: 0 }}
|
|
61
|
+
animate={{ opacity: 1 }}
|
|
62
|
+
transition={{ delay: 0.8, duration: 0.6 }}
|
|
63
|
+
className="mt-4 text-lg md:text-xl text-muted-foreground text-center max-w-xl"
|
|
64
|
+
>
|
|
65
|
+
Self-evolving intelligence. Zero-friction setup.
|
|
66
|
+
</motion.p>
|
|
67
|
+
|
|
68
|
+
{/* Divider line */}
|
|
69
|
+
<motion.div
|
|
70
|
+
initial={{ scaleX: 0 }}
|
|
71
|
+
animate={{ scaleX: 1 }}
|
|
72
|
+
transition={{ delay: 1.0, duration: 0.8, ease: "easeOut" }}
|
|
73
|
+
className="mt-10 w-full max-w-2xl h-px bg-gradient-to-r from-transparent via-white/10 to-transparent"
|
|
74
|
+
/>
|
|
75
|
+
</motion.section>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useRef, useEffect, useCallback } from "react";
|
|
4
|
+
|
|
5
|
+
interface ClickSparkProps {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
sparkColor?: string;
|
|
8
|
+
sparkSize?: number;
|
|
9
|
+
sparkRadius?: number;
|
|
10
|
+
sparkCount?: number;
|
|
11
|
+
duration?: number;
|
|
12
|
+
className?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default function ClickSpark({
|
|
16
|
+
children,
|
|
17
|
+
sparkColor = "#8b5cf6",
|
|
18
|
+
sparkSize = 8,
|
|
19
|
+
sparkRadius = 20,
|
|
20
|
+
sparkCount = 8,
|
|
21
|
+
duration = 400,
|
|
22
|
+
className = "",
|
|
23
|
+
}: ClickSparkProps) {
|
|
24
|
+
const canvasRef = useRef<HTMLCanvasElement>(null);
|
|
25
|
+
const sparksRef = useRef<
|
|
26
|
+
Array<{ x: number; y: number; angle: number; startTime: number }>
|
|
27
|
+
>([]);
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
const canvas = canvasRef.current;
|
|
31
|
+
if (!canvas) return;
|
|
32
|
+
const parent = canvas.parentElement;
|
|
33
|
+
if (!parent) return;
|
|
34
|
+
|
|
35
|
+
const resize = () => {
|
|
36
|
+
const { width, height } = parent.getBoundingClientRect();
|
|
37
|
+
canvas.width = width;
|
|
38
|
+
canvas.height = height;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
resize();
|
|
42
|
+
const ro = new ResizeObserver(resize);
|
|
43
|
+
ro.observe(parent);
|
|
44
|
+
|
|
45
|
+
const ctx = canvas.getContext("2d");
|
|
46
|
+
if (!ctx) return;
|
|
47
|
+
|
|
48
|
+
let raf: number;
|
|
49
|
+
|
|
50
|
+
const draw = (ts: number) => {
|
|
51
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
52
|
+
|
|
53
|
+
sparksRef.current = sparksRef.current.filter((spark) => {
|
|
54
|
+
const elapsed = ts - spark.startTime;
|
|
55
|
+
if (elapsed > duration) return false;
|
|
56
|
+
|
|
57
|
+
const progress = elapsed / duration;
|
|
58
|
+
const dist = sparkRadius * progress;
|
|
59
|
+
const opacity = 1 - progress;
|
|
60
|
+
|
|
61
|
+
const x = spark.x + Math.cos(spark.angle) * dist;
|
|
62
|
+
const y = spark.y + Math.sin(spark.angle) * dist;
|
|
63
|
+
|
|
64
|
+
ctx.beginPath();
|
|
65
|
+
ctx.arc(x, y, sparkSize * (1 - progress) * 0.5, 0, Math.PI * 2);
|
|
66
|
+
ctx.fillStyle = sparkColor;
|
|
67
|
+
ctx.globalAlpha = opacity;
|
|
68
|
+
ctx.fill();
|
|
69
|
+
ctx.globalAlpha = 1;
|
|
70
|
+
|
|
71
|
+
return true;
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
raf = requestAnimationFrame(draw);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
raf = requestAnimationFrame(draw);
|
|
78
|
+
|
|
79
|
+
return () => {
|
|
80
|
+
cancelAnimationFrame(raf);
|
|
81
|
+
ro.disconnect();
|
|
82
|
+
};
|
|
83
|
+
}, [sparkColor, sparkSize, sparkRadius, sparkCount, duration]);
|
|
84
|
+
|
|
85
|
+
const handleClick = useCallback(
|
|
86
|
+
(e: React.MouseEvent) => {
|
|
87
|
+
const canvas = canvasRef.current;
|
|
88
|
+
if (!canvas) return;
|
|
89
|
+
const rect = canvas.getBoundingClientRect();
|
|
90
|
+
const x = e.clientX - rect.left;
|
|
91
|
+
const y = e.clientY - rect.top;
|
|
92
|
+
const now = performance.now();
|
|
93
|
+
|
|
94
|
+
for (let i = 0; i < sparkCount; i++) {
|
|
95
|
+
sparksRef.current.push({
|
|
96
|
+
x,
|
|
97
|
+
y,
|
|
98
|
+
angle: (Math.PI * 2 * i) / sparkCount,
|
|
99
|
+
startTime: now,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
[sparkCount]
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
return (
|
|
107
|
+
<div className={`relative ${className}`} onClick={handleClick}>
|
|
108
|
+
<canvas
|
|
109
|
+
ref={canvasRef}
|
|
110
|
+
className="absolute inset-0 pointer-events-none"
|
|
111
|
+
style={{ zIndex: 50 }}
|
|
112
|
+
/>
|
|
113
|
+
{children}
|
|
114
|
+
</div>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useRef, useEffect, useCallback, useState } from "react";
|
|
4
|
+
import { useInView, useMotionValue, useSpring } from "framer-motion";
|
|
5
|
+
|
|
6
|
+
interface CountUpProps {
|
|
7
|
+
to: number;
|
|
8
|
+
from?: number;
|
|
9
|
+
direction?: "up" | "down";
|
|
10
|
+
delay?: number;
|
|
11
|
+
duration?: number;
|
|
12
|
+
className?: string;
|
|
13
|
+
separator?: string;
|
|
14
|
+
onStart?: () => void;
|
|
15
|
+
onEnd?: () => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default function CountUp({
|
|
19
|
+
to,
|
|
20
|
+
from = 0,
|
|
21
|
+
direction = "up",
|
|
22
|
+
delay = 0,
|
|
23
|
+
duration = 2,
|
|
24
|
+
className = "",
|
|
25
|
+
separator = "",
|
|
26
|
+
onStart,
|
|
27
|
+
onEnd,
|
|
28
|
+
}: CountUpProps) {
|
|
29
|
+
const ref = useRef<HTMLSpanElement>(null);
|
|
30
|
+
const motionValue = useMotionValue(direction === "down" ? to : from);
|
|
31
|
+
const damping = 20 + 40 * (1 / duration);
|
|
32
|
+
const stiffness = 100 * (1 / duration);
|
|
33
|
+
const springValue = useSpring(motionValue, { damping, stiffness });
|
|
34
|
+
const isInView = useInView(ref, { once: true, margin: "0px" });
|
|
35
|
+
const [displayValue, setDisplayValue] = useState<string>(
|
|
36
|
+
() => formatValue(direction === "down" ? to : from, from, to, separator)
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const maxDecimals = Math.max(
|
|
40
|
+
getDecimalPlaces(from),
|
|
41
|
+
getDecimalPlaces(to)
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
// Spring animation → state update (never mutates DOM)
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
const unsubscribe = springValue.on("change", (latest) => {
|
|
47
|
+
setDisplayValue(formatValue(latest, from, to, separator));
|
|
48
|
+
});
|
|
49
|
+
return unsubscribe;
|
|
50
|
+
}, [springValue, from, to, separator]);
|
|
51
|
+
|
|
52
|
+
// Trigger animation on enter viewport
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
if (isInView) {
|
|
55
|
+
onStart?.();
|
|
56
|
+
const timeout = setTimeout(() => {
|
|
57
|
+
motionValue.set(direction === "down" ? from : to);
|
|
58
|
+
}, delay * 1000);
|
|
59
|
+
const endTimeout = setTimeout(() => {
|
|
60
|
+
onEnd?.();
|
|
61
|
+
}, delay * 1000 + duration * 1000);
|
|
62
|
+
return () => {
|
|
63
|
+
clearTimeout(timeout);
|
|
64
|
+
clearTimeout(endTimeout);
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}, [isInView, from, to, direction, delay, duration, motionValue, onStart, onEnd]);
|
|
68
|
+
|
|
69
|
+
return <span ref={ref} className={className}>{displayValue}</span>;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ── Helpers ──
|
|
73
|
+
|
|
74
|
+
function getDecimalPlaces(num: number): number {
|
|
75
|
+
const str = num.toString();
|
|
76
|
+
if (str.includes(".")) {
|
|
77
|
+
const decimals = str.split(".")[1];
|
|
78
|
+
if (parseInt(decimals) !== 0) return decimals.length;
|
|
79
|
+
}
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function formatValue(
|
|
84
|
+
value: number,
|
|
85
|
+
from: number,
|
|
86
|
+
to: number,
|
|
87
|
+
separator: string
|
|
88
|
+
): string {
|
|
89
|
+
const maxDecimals = Math.max(getDecimalPlaces(from), getDecimalPlaces(to));
|
|
90
|
+
const hasDecimals = maxDecimals > 0;
|
|
91
|
+
const options: Intl.NumberFormatOptions = {
|
|
92
|
+
useGrouping: !!separator,
|
|
93
|
+
minimumFractionDigits: hasDecimals ? maxDecimals : 0,
|
|
94
|
+
maximumFractionDigits: hasDecimals ? maxDecimals : 0,
|
|
95
|
+
};
|
|
96
|
+
const formatted = new Intl.NumberFormat("en-US", options).format(value);
|
|
97
|
+
return separator ? formatted.replace(/,/g, separator) : formatted;
|
|
98
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState, useRef, useEffect } from "react";
|
|
4
|
+
import { motion, AnimatePresence } from "framer-motion";
|
|
5
|
+
import { ChevronDown, Check } from "lucide-react";
|
|
6
|
+
|
|
7
|
+
interface Option {
|
|
8
|
+
value: string;
|
|
9
|
+
label: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface DarkSelectProps {
|
|
13
|
+
value: string;
|
|
14
|
+
onChange: (value: string) => void;
|
|
15
|
+
options: Option[];
|
|
16
|
+
placeholder?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default function DarkSelect({
|
|
20
|
+
value,
|
|
21
|
+
onChange,
|
|
22
|
+
options,
|
|
23
|
+
placeholder = "Select...",
|
|
24
|
+
}: DarkSelectProps) {
|
|
25
|
+
const [open, setOpen] = useState(false);
|
|
26
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
27
|
+
|
|
28
|
+
const selected = options.find((o) => o.value === value);
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
const handleClick = (e: MouseEvent) => {
|
|
32
|
+
if (ref.current && !ref.current.contains(e.target as Node)) {
|
|
33
|
+
setOpen(false);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
document.addEventListener("mousedown", handleClick);
|
|
37
|
+
return () => document.removeEventListener("mousedown", handleClick);
|
|
38
|
+
}, []);
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<div ref={ref} className="relative">
|
|
42
|
+
<button
|
|
43
|
+
type="button"
|
|
44
|
+
onClick={() => setOpen(!open)}
|
|
45
|
+
className="w-full flex items-center justify-between px-4 py-2.5 rounded-xl bg-[#1a1a1a] border border-white/[0.08] text-sm text-[#e5e5e5] hover:border-white/[0.15] transition-colors focus:outline-none focus:border-accent-violet/50"
|
|
46
|
+
>
|
|
47
|
+
<span className={!selected ? "text-[#666]" : ""}>
|
|
48
|
+
{selected ? selected.label : placeholder}
|
|
49
|
+
</span>
|
|
50
|
+
<ChevronDown
|
|
51
|
+
className={`w-4 h-4 text-[#888] transition-transform ${
|
|
52
|
+
open ? "rotate-180" : ""
|
|
53
|
+
}`}
|
|
54
|
+
/>
|
|
55
|
+
</button>
|
|
56
|
+
|
|
57
|
+
<AnimatePresence>
|
|
58
|
+
{open && (
|
|
59
|
+
<motion.div
|
|
60
|
+
initial={{ opacity: 0, y: -4 }}
|
|
61
|
+
animate={{ opacity: 1, y: 0 }}
|
|
62
|
+
exit={{ opacity: 0, y: -4 }}
|
|
63
|
+
transition={{ duration: 0.15 }}
|
|
64
|
+
className="absolute z-50 top-full left-0 right-0 mt-1 rounded-xl bg-[#121212] border border-white/[0.08] shadow-2xl overflow-hidden max-h-60 overflow-y-auto"
|
|
65
|
+
>
|
|
66
|
+
{options.length === 0 ? (
|
|
67
|
+
<div className="px-4 py-3 text-sm text-[#666]">No options</div>
|
|
68
|
+
) : (
|
|
69
|
+
options.map((opt) => (
|
|
70
|
+
<button
|
|
71
|
+
key={opt.value}
|
|
72
|
+
type="button"
|
|
73
|
+
onClick={() => {
|
|
74
|
+
onChange(opt.value);
|
|
75
|
+
setOpen(false);
|
|
76
|
+
}}
|
|
77
|
+
className={`w-full flex items-center justify-between px-4 py-2.5 text-sm transition-colors ${
|
|
78
|
+
opt.value === value
|
|
79
|
+
? "bg-accent-violet/15 text-[#ffffff]"
|
|
80
|
+
: "text-[#cccccc] hover:bg-white/[0.06] hover:text-[#ffffff]"
|
|
81
|
+
}`}
|
|
82
|
+
>
|
|
83
|
+
<span className="truncate">{opt.label}</span>
|
|
84
|
+
{opt.value === value && (
|
|
85
|
+
<Check className="w-3.5 h-3.5 text-accent-violet flex-shrink-0" />
|
|
86
|
+
)}
|
|
87
|
+
</button>
|
|
88
|
+
))
|
|
89
|
+
)}
|
|
90
|
+
</motion.div>
|
|
91
|
+
)}
|
|
92
|
+
</AnimatePresence>
|
|
93
|
+
</div>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState, useRef, useMemo, useCallback } from "react";
|
|
4
|
+
import { motion } from "framer-motion";
|
|
5
|
+
|
|
6
|
+
interface DecryptedTextProps {
|
|
7
|
+
text: string;
|
|
8
|
+
speed?: number;
|
|
9
|
+
maxIterations?: number;
|
|
10
|
+
sequential?: boolean;
|
|
11
|
+
revealDirection?: "start" | "end" | "center";
|
|
12
|
+
useOriginalCharsOnly?: boolean;
|
|
13
|
+
characters?: string;
|
|
14
|
+
className?: string;
|
|
15
|
+
parentClassName?: string;
|
|
16
|
+
encryptedClassName?: string;
|
|
17
|
+
animateOn?: "hover" | "view" | "click";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default function DecryptedText({
|
|
21
|
+
text,
|
|
22
|
+
speed = 50,
|
|
23
|
+
maxIterations = 10,
|
|
24
|
+
sequential = false,
|
|
25
|
+
revealDirection = "start",
|
|
26
|
+
useOriginalCharsOnly = false,
|
|
27
|
+
characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$%^&*()_+",
|
|
28
|
+
className = "",
|
|
29
|
+
parentClassName = "",
|
|
30
|
+
encryptedClassName = "",
|
|
31
|
+
animateOn = "hover",
|
|
32
|
+
}: DecryptedTextProps) {
|
|
33
|
+
const [displayText, setDisplayText] = useState(text);
|
|
34
|
+
const [isAnimating, setIsAnimating] = useState(false);
|
|
35
|
+
const [revealedIndices, setRevealedIndices] = useState<Set<number>>(new Set());
|
|
36
|
+
const containerRef = useRef<HTMLSpanElement>(null);
|
|
37
|
+
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
|
38
|
+
|
|
39
|
+
const availableChars = useMemo(() => {
|
|
40
|
+
return useOriginalCharsOnly
|
|
41
|
+
? Array.from(new Set(text.split(""))).filter((c) => c !== " ")
|
|
42
|
+
: characters.split("");
|
|
43
|
+
}, [useOriginalCharsOnly, text, characters]);
|
|
44
|
+
|
|
45
|
+
const shuffleText = useCallback(
|
|
46
|
+
(original: string, revealed: Set<number>) => {
|
|
47
|
+
return original
|
|
48
|
+
.split("")
|
|
49
|
+
.map((char, i) => {
|
|
50
|
+
if (char === " ") return " ";
|
|
51
|
+
if (revealed.has(i)) return original[i];
|
|
52
|
+
return availableChars[Math.floor(Math.random() * availableChars.length)];
|
|
53
|
+
})
|
|
54
|
+
.join("");
|
|
55
|
+
},
|
|
56
|
+
[availableChars]
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const getOrder = useCallback(
|
|
60
|
+
(len: number) => {
|
|
61
|
+
const order: number[] = [];
|
|
62
|
+
if (revealDirection === "start") {
|
|
63
|
+
for (let i = 0; i < len; i++) order.push(i);
|
|
64
|
+
} else if (revealDirection === "end") {
|
|
65
|
+
for (let i = len - 1; i >= 0; i--) order.push(i);
|
|
66
|
+
} else {
|
|
67
|
+
const mid = Math.floor(len / 2);
|
|
68
|
+
order.push(mid);
|
|
69
|
+
for (let i = 1; i <= mid; i++) {
|
|
70
|
+
if (mid - i >= 0) order.push(mid - i);
|
|
71
|
+
if (mid + i < len) order.push(mid + i);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return order;
|
|
75
|
+
},
|
|
76
|
+
[revealDirection]
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
const startAnimation = useCallback(() => {
|
|
80
|
+
if (isAnimating) return;
|
|
81
|
+
setIsAnimating(true);
|
|
82
|
+
setRevealedIndices(new Set());
|
|
83
|
+
|
|
84
|
+
let iteration = 0;
|
|
85
|
+
const order = getOrder(text.length);
|
|
86
|
+
|
|
87
|
+
intervalRef.current = setInterval(() => {
|
|
88
|
+
if (sequential) {
|
|
89
|
+
setRevealedIndices((prev) => {
|
|
90
|
+
const next = new Set(prev);
|
|
91
|
+
const nextIdx = order[next.size];
|
|
92
|
+
if (nextIdx !== undefined) next.add(nextIdx);
|
|
93
|
+
if (next.size >= text.length) {
|
|
94
|
+
clearInterval(intervalRef.current!);
|
|
95
|
+
setIsAnimating(false);
|
|
96
|
+
}
|
|
97
|
+
return next;
|
|
98
|
+
});
|
|
99
|
+
} else {
|
|
100
|
+
iteration++;
|
|
101
|
+
const revealed = new Set<number>();
|
|
102
|
+
const numToReveal = Math.floor((iteration / maxIterations) * text.length);
|
|
103
|
+
for (let i = 0; i < numToReveal && i < order.length; i++) {
|
|
104
|
+
revealed.add(order[i]);
|
|
105
|
+
}
|
|
106
|
+
setRevealedIndices(revealed);
|
|
107
|
+
if (iteration >= maxIterations) {
|
|
108
|
+
clearInterval(intervalRef.current!);
|
|
109
|
+
setIsAnimating(false);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}, speed);
|
|
113
|
+
}, [isAnimating, text, sequential, maxIterations, speed, getOrder]);
|
|
114
|
+
|
|
115
|
+
useEffect(() => {
|
|
116
|
+
if (animateOn === "view") {
|
|
117
|
+
const observer = new IntersectionObserver(
|
|
118
|
+
([entry]) => {
|
|
119
|
+
if (entry.isIntersecting) startAnimation();
|
|
120
|
+
},
|
|
121
|
+
{ threshold: 0.1 }
|
|
122
|
+
);
|
|
123
|
+
if (containerRef.current) observer.observe(containerRef.current);
|
|
124
|
+
return () => observer.disconnect();
|
|
125
|
+
}
|
|
126
|
+
}, [animateOn, startAnimation]);
|
|
127
|
+
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
if (isAnimating) {
|
|
130
|
+
setDisplayText(shuffleText(text, revealedIndices));
|
|
131
|
+
} else if (revealedIndices.size === 0 && animateOn !== "view") {
|
|
132
|
+
setDisplayText(text);
|
|
133
|
+
} else {
|
|
134
|
+
setDisplayText(
|
|
135
|
+
text
|
|
136
|
+
.split("")
|
|
137
|
+
.map((c, i) => (revealedIndices.has(i) ? c : c === " " ? " " : availableChars[Math.floor(Math.random() * availableChars.length)]))
|
|
138
|
+
.join("")
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
}, [isAnimating, revealedIndices, text, shuffleText, availableChars, animateOn]);
|
|
142
|
+
|
|
143
|
+
useEffect(() => {
|
|
144
|
+
return () => {
|
|
145
|
+
if (intervalRef.current) clearInterval(intervalRef.current);
|
|
146
|
+
};
|
|
147
|
+
}, []);
|
|
148
|
+
|
|
149
|
+
return (
|
|
150
|
+
<motion.span
|
|
151
|
+
ref={containerRef}
|
|
152
|
+
className={`inline-block whitespace-pre-wrap ${parentClassName}`}
|
|
153
|
+
onMouseEnter={animateOn === "hover" ? startAnimation : undefined}
|
|
154
|
+
onClick={animateOn === "click" ? startAnimation : undefined}
|
|
155
|
+
>
|
|
156
|
+
<span className={isAnimating ? encryptedClassName : className}>
|
|
157
|
+
{displayText}
|
|
158
|
+
</span>
|
|
159
|
+
</motion.span>
|
|
160
|
+
);
|
|
161
|
+
}
|