Spaces:
Configuration error
Configuration error
Upload 18 files
Browse files- App.tsx +164 -0
- Dockerfile +13 -0
- README.md +52 -11
- constants.ts +67 -0
- globals.d.ts +24 -0
- index.css +100 -0
- index.html +38 -0
- index.tsx +24 -0
- metadata.json +8 -0
- package-lock.json +0 -0
- package.json +34 -0
- postcss.config.js +6 -0
- services +0 -0
- tailwind.config.js +33 -0
- tsconfig.json +27 -0
- tsconfig.server.json +16 -0
- types.ts +47 -0
- vite.config.ts +37 -0
App.tsx
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React, { Suspense, useCallback, useMemo, useState, useEffect } from 'react';
|
| 2 |
+
import { ErrorBoundary } from './components/ErrorBoundary.tsx';
|
| 3 |
+
import { useGlobalState } from './contexts/GlobalStateContext.tsx';
|
| 4 |
+
import { logEvent } from './services/telemetryService.ts';
|
| 5 |
+
import { ALL_FEATURES, FEATURES_MAP } from './components/features/index.ts';
|
| 6 |
+
import type { ViewType, FeatureId, SidebarItem } from './types.ts';
|
| 7 |
+
import { DownloadManager } from './components/DownloadManager.tsx';
|
| 8 |
+
import { LeftSidebar } from './components/LeftSidebar.tsx';
|
| 9 |
+
import { StatusBar } from './components/StatusBar.tsx';
|
| 10 |
+
import { CommandPalette } from './components/CommandPalette.tsx';
|
| 11 |
+
import { SettingsView } from './components/SettingsView.tsx';
|
| 12 |
+
import { Cog6ToothIcon, HomeIcon } from './components/icons/InterfaceIcons.tsx';
|
| 13 |
+
import { AiCommandCenter } from './components/features/AiCommandCenter.tsx';
|
| 14 |
+
import { LoginView } from './components/LoginView.tsx';
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
export const LoadingIndicator: React.FC = () => (
|
| 18 |
+
<div className="w-full h-full flex items-center justify-center bg-surface">
|
| 19 |
+
<div className="flex items-center justify-center space-x-2">
|
| 20 |
+
<div className="w-4 h-4 rounded-full bg-primary animate-pulse" style={{ animationDelay: '0s' }}></div>
|
| 21 |
+
<div className="w-4 h-4 rounded-full bg-primary animate-pulse" style={{ animationDelay: '0.2s' }}></div>
|
| 22 |
+
<div className="w-4 h-4 rounded-full bg-primary animate-pulse" style={{ animationDelay: '0.4s' }}></div>
|
| 23 |
+
<span className="text-text-secondary ml-2">Loading Feature...</span>
|
| 24 |
+
</div>
|
| 25 |
+
</div>
|
| 26 |
+
);
|
| 27 |
+
|
| 28 |
+
interface LocalStorageConsentModalProps {
|
| 29 |
+
onAccept: () => void;
|
| 30 |
+
onDecline: () => void;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
const LocalStorageConsentModal: React.FC<LocalStorageConsentModalProps> = ({ onAccept, onDecline }) => {
|
| 34 |
+
return (
|
| 35 |
+
<div className="fixed inset-0 bg-gray-900/80 backdrop-blur-sm z-50 flex items-center justify-center fade-in">
|
| 36 |
+
<div
|
| 37 |
+
className="bg-surface border border-border rounded-2xl shadow-2xl shadow-black/50 w-full max-w-md m-4 p-8 text-center animate-pop-in"
|
| 38 |
+
>
|
| 39 |
+
<h2 className="text-2xl mb-4">Store Data Locally?</h2>
|
| 40 |
+
<p className="text-text-secondary mb-6">
|
| 41 |
+
This application uses your browser's local storage to save your settings and remember your progress between sessions. This data stays on your computer and is not shared.
|
| 42 |
+
</p>
|
| 43 |
+
<div className="flex justify-center gap-4">
|
| 44 |
+
<button
|
| 45 |
+
onClick={onDecline}
|
| 46 |
+
className="px-6 py-2 bg-surface border border-border text-text-primary font-bold rounded-md hover:bg-gray-100 transition-colors"
|
| 47 |
+
>
|
| 48 |
+
Decline
|
| 49 |
+
</button>
|
| 50 |
+
<button
|
| 51 |
+
onClick={onAccept}
|
| 52 |
+
className="btn-primary px-6 py-2"
|
| 53 |
+
>
|
| 54 |
+
Accept
|
| 55 |
+
</button>
|
| 56 |
+
</div>
|
| 57 |
+
</div>
|
| 58 |
+
</div>
|
| 59 |
+
);
|
| 60 |
+
};
|
| 61 |
+
|
| 62 |
+
const App: React.FC = () => {
|
| 63 |
+
const { state, dispatch } = useGlobalState();
|
| 64 |
+
const { activeView, viewProps, hiddenFeatures, isAuthenticated } = state;
|
| 65 |
+
const [isCommandPaletteOpen, setCommandPaletteOpen] = useState(false);
|
| 66 |
+
const [showConsentModal, setShowConsentModal] = useState(false);
|
| 67 |
+
|
| 68 |
+
useEffect(() => {
|
| 69 |
+
try {
|
| 70 |
+
const consent = localStorage.getItem('devcore_ls_consent');
|
| 71 |
+
if (!consent) {
|
| 72 |
+
setShowConsentModal(true);
|
| 73 |
+
}
|
| 74 |
+
} catch (e) {
|
| 75 |
+
console.warn("Could not access localStorage.", e);
|
| 76 |
+
}
|
| 77 |
+
}, []);
|
| 78 |
+
|
| 79 |
+
useEffect(() => {
|
| 80 |
+
const handleKeyDown = (e: KeyboardEvent) => {
|
| 81 |
+
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
|
| 82 |
+
e.preventDefault();
|
| 83 |
+
setCommandPaletteOpen(isOpen => !isOpen);
|
| 84 |
+
}
|
| 85 |
+
};
|
| 86 |
+
window.addEventListener('keydown', handleKeyDown);
|
| 87 |
+
return () => window.removeEventListener('keydown', handleKeyDown);
|
| 88 |
+
}, []);
|
| 89 |
+
|
| 90 |
+
const handleAcceptConsent = () => {
|
| 91 |
+
try {
|
| 92 |
+
localStorage.setItem('devcore_ls_consent', 'granted');
|
| 93 |
+
window.location.reload();
|
| 94 |
+
} catch (e) {
|
| 95 |
+
console.error("Could not write to localStorage.", e);
|
| 96 |
+
setShowConsentModal(false);
|
| 97 |
+
}
|
| 98 |
+
};
|
| 99 |
+
|
| 100 |
+
const handleDeclineConsent = () => {
|
| 101 |
+
try {
|
| 102 |
+
localStorage.setItem('devcore_ls_consent', 'denied');
|
| 103 |
+
} catch (e) {
|
| 104 |
+
console.error("Could not write to localStorage.", e);
|
| 105 |
+
}
|
| 106 |
+
setShowConsentModal(false);
|
| 107 |
+
};
|
| 108 |
+
|
| 109 |
+
const handleViewChange = useCallback((view: ViewType, props: any = {}) => {
|
| 110 |
+
dispatch({ type: 'SET_VIEW', payload: { view, props } });
|
| 111 |
+
logEvent('view_changed', { view });
|
| 112 |
+
setCommandPaletteOpen(false);
|
| 113 |
+
}, [dispatch]);
|
| 114 |
+
|
| 115 |
+
const sidebarItems: SidebarItem[] = useMemo(() => [
|
| 116 |
+
{ id: 'ai-command-center', label: 'Command Center', icon: <HomeIcon />, view: 'ai-command-center' },
|
| 117 |
+
...ALL_FEATURES
|
| 118 |
+
.filter(feature => !hiddenFeatures.includes(feature.id) && feature.id !== 'ai-command-center')
|
| 119 |
+
.map(feature => ({
|
| 120 |
+
id: feature.id,
|
| 121 |
+
label: feature.name,
|
| 122 |
+
icon: feature.icon,
|
| 123 |
+
view: feature.id as ViewType,
|
| 124 |
+
})),
|
| 125 |
+
{ id: 'settings', label: 'Settings', icon: <Cog6ToothIcon />, view: 'settings' },
|
| 126 |
+
], [hiddenFeatures]);
|
| 127 |
+
|
| 128 |
+
const ActiveComponent = useMemo(() => {
|
| 129 |
+
if (activeView === 'settings') return SettingsView;
|
| 130 |
+
// Fallback to command center if no view is matched.
|
| 131 |
+
return FEATURES_MAP.get(activeView as string)?.component ?? AiCommandCenter;
|
| 132 |
+
}, [activeView]);
|
| 133 |
+
|
| 134 |
+
if (!isAuthenticated) {
|
| 135 |
+
return <LoginView />;
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
return (
|
| 139 |
+
<div className="h-screen w-screen font-sans overflow-hidden bg-background">
|
| 140 |
+
{showConsentModal && <LocalStorageConsentModal onAccept={handleAcceptConsent} onDecline={handleDeclineConsent} />}
|
| 141 |
+
<div className="relative flex h-full w-full">
|
| 142 |
+
<LeftSidebar items={sidebarItems} activeView={state.activeView} onNavigate={handleViewChange} />
|
| 143 |
+
<div className="flex-1 flex min-w-0">
|
| 144 |
+
<div className="flex-1 flex flex-col min-w-0">
|
| 145 |
+
<main className="relative flex-1 min-w-0 bg-surface/50 overflow-y-auto">
|
| 146 |
+
<ErrorBoundary>
|
| 147 |
+
<Suspense fallback={<LoadingIndicator />}>
|
| 148 |
+
<div key={activeView} className="fade-in w-full h-full">
|
| 149 |
+
<ActiveComponent {...viewProps} />
|
| 150 |
+
</div>
|
| 151 |
+
</Suspense>
|
| 152 |
+
</ErrorBoundary>
|
| 153 |
+
<DownloadManager />
|
| 154 |
+
</main>
|
| 155 |
+
<StatusBar bgImageStatus="loaded" />
|
| 156 |
+
</div>
|
| 157 |
+
</div>
|
| 158 |
+
<CommandPalette isOpen={isCommandPaletteOpen} onClose={() => setCommandPaletteOpen(false)} onSelect={handleViewChange} />
|
| 159 |
+
</div>
|
| 160 |
+
</div>
|
| 161 |
+
);
|
| 162 |
+
};
|
| 163 |
+
|
| 164 |
+
export default App;
|
Dockerfile
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Build Stage
|
| 2 |
+
FROM node:18-alpine AS build
|
| 3 |
+
WORKDIR /app
|
| 4 |
+
COPY package*.json ./
|
| 5 |
+
RUN npm install
|
| 6 |
+
COPY . .
|
| 7 |
+
RUN npm run build
|
| 8 |
+
|
| 9 |
+
# Production Stage
|
| 10 |
+
FROM nginx:stable-alpine AS production
|
| 11 |
+
COPY --from=build /app/build /usr/share/nginx/html
|
| 12 |
+
EXPOSE 80
|
| 13 |
+
CMD ["nginx", "-g", "daemon off;"]
|
README.md
CHANGED
|
@@ -1,11 +1,52 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# DevCore AI Toolkit
|
| 2 |
+
|
| 3 |
+
DevCore is a developer-centric web application designed to showcase the power of AI in the development process. It's a static application that can be deployed to any modern hosting provider.
|
| 4 |
+
|
| 5 |
+
## Key Features
|
| 6 |
+
|
| 7 |
+
- **Purely Static**: Runs entirely in the browser with no server backend required.
|
| 8 |
+
- **Easy Deployment**: Deploy to any static hosting provider like Hugging Face Spaces, Vercel, or Netlify.
|
| 9 |
+
- **AI Feature Builder**: Describe a new UI component, and the AI will generate the TSX/JSX code, unit tests, and a conventional commit message.
|
| 10 |
+
- **AI Code Explainer**: Paste any code snippet and get a detailed, easy-to-understand explanation and a visual flowchart generated by Gemini.
|
| 11 |
+
- **Comprehensive Tooling**: Includes a RegEx Sandbox, Snippet Vault, Code Migrator, and dozens of other AI-powered and simulated developer tools.
|
| 12 |
+
|
| 13 |
+
## Local Development Setup
|
| 14 |
+
|
| 15 |
+
**Prerequisites:** [Node.js](https://nodejs.org/)
|
| 16 |
+
|
| 17 |
+
1. **Clone the repository.**
|
| 18 |
+
|
| 19 |
+
2. **Install dependencies:**
|
| 20 |
+
```bash
|
| 21 |
+
npm install
|
| 22 |
+
```
|
| 23 |
+
|
| 24 |
+
3. **Set up your local environment variables:**
|
| 25 |
+
Create a file named `.env.local` in the root of the project and add your Gemini API key:
|
| 26 |
+
```
|
| 27 |
+
GEMINI_API_KEY=your_gemini_api_key_here
|
| 28 |
+
```
|
| 29 |
+
|
| 30 |
+
4. **Run the development server:**
|
| 31 |
+
```bash
|
| 32 |
+
npm run dev
|
| 33 |
+
```
|
| 34 |
+
The application will be available at `http://localhost:5173`.
|
| 35 |
+
|
| 36 |
+
## Deployment
|
| 37 |
+
|
| 38 |
+
This is a static web application that calls the Gemini API directly from the client. To deploy it, you need to:
|
| 39 |
+
|
| 40 |
+
1. **Build the Project**:
|
| 41 |
+
```bash
|
| 42 |
+
npm run build
|
| 43 |
+
```
|
| 44 |
+
This creates a `web` directory with your static app.
|
| 45 |
+
|
| 46 |
+
2. **Set Environment Variable**:
|
| 47 |
+
Your hosting provider (like Hugging Face Spaces, Vercel, Netlify, etc.) needs to have the `GEMINI_API_KEY` environment variable set during the build process.
|
| 48 |
+
- **Name**: `GEMINI_API_KEY`
|
| 49 |
+
- **Value**: Your actual Gemini API key.
|
| 50 |
+
|
| 51 |
+
3. **Deploy**:
|
| 52 |
+
Deploy the contents of the `web` directory as a static site. Ensure your hosting provider's build command is `npm run build`.
|
constants.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React from 'react';
|
| 2 |
+
import {
|
| 3 |
+
CommandCenterIcon, CodeExplainerIcon, FeatureBuilderIcon, CodeMigratorIcon, ThemeDesignerIcon, SnippetVaultIcon,
|
| 4 |
+
DevNotesIcon, UnitTestGeneratorIcon, CommitGeneratorIcon, GitLogAnalyzerIcon, ConcurrencyAnalyzerIcon, RegexSandboxIcon,
|
| 5 |
+
PromptCraftPadIcon, CodeFormatterIcon, JsonTreeIcon, CssGridEditorIcon, SchemaDesignerIcon, PwaManifestEditorIcon,
|
| 6 |
+
MarkdownSlidesIcon, ScreenshotToComponentIcon, FontPreviewIcon, SvgPathEditorIcon, StyleTransferIcon, CodingChallengeIcon,
|
| 7 |
+
FontPairingIcon, CodeReviewBotIcon, PrSummaryGeneratorIcon, ChangelogGeneratorIcon, CronJobBuilderIcon, MoodboardIcon,
|
| 8 |
+
AsyncCallTreeIcon, AudioToCodeIcon, CodeDiffGhostIcon, CodeSpellCheckerIcon, ColorPaletteGeneratorIcon, LogicFlowBuilderIcon,
|
| 9 |
+
MetaTagEditorIcon, NetworkVisualizerIcon, PrGeneratorIcon, ResponsiveTesterIcon, SassCompilerIcon, ImageGeneratorIcon, XbrlConverterIcon
|
| 10 |
+
} from './components/icons/CustomFeatureIcons.tsx';
|
| 11 |
+
|
| 12 |
+
export const CHROME_VIEW_IDS = ['features-list'] as const;
|
| 13 |
+
|
| 14 |
+
export const SLOTS = ['Core', 'AI Tools', 'Frontend', 'Testing', 'Database', 'Productivity'] as const;
|
| 15 |
+
export type SlotCategory = typeof SLOTS[number];
|
| 16 |
+
|
| 17 |
+
export const FEATURE_CATEGORIES = ['Core', 'AI Tools', 'Frontend', 'Testing', 'Database', 'Data', 'Productivity', 'Git', 'Deployment', 'Security', 'Workflow'] as const;
|
| 18 |
+
export type FeatureCategory = typeof FEATURE_CATEGORIES[number];
|
| 19 |
+
|
| 20 |
+
// This is the raw data, to be "compiled" by features/index.ts
|
| 21 |
+
export const RAW_FEATURES = [
|
| 22 |
+
{ id: "ai-command-center", name: "AI Command Center", description: "Use natural language to navigate and control the toolkit.", icon: React.createElement(CommandCenterIcon), category: "Core" },
|
| 23 |
+
{ id: "ai-image-generator", name: "AI Image Generator", description: "Generate high-quality images from a text prompt.", icon: React.createElement(ImageGeneratorIcon), category: "AI Tools" },
|
| 24 |
+
{ id: "ai-code-explainer", name: "AI Code Explainer", description: "Get a structured analysis of code, including complexity.", icon: React.createElement(CodeExplainerIcon), category: "AI Tools" },
|
| 25 |
+
{ id: "ai-feature-builder", name: "AI Feature Builder", description: "Generate code, tests, and commit messages.", icon: React.createElement(FeatureBuilderIcon), category: "AI Tools" },
|
| 26 |
+
{ id: "ai-code-migrator", name: "AI Code Migrator", description: "Translate code between languages & frameworks.", icon: React.createElement(CodeMigratorIcon), category: "AI Tools" },
|
| 27 |
+
{ id: "theme-designer", name: "AI Theme Designer", description: "Generate, fine-tune, and export UI color themes from a text description.", icon: React.createElement(ThemeDesignerIcon), category: "AI Tools" },
|
| 28 |
+
{ id: "portable-snippet-vault", name: "Snippet Vault", description: "Store, search, tag, and enhance reusable code snippets with AI.", icon: React.createElement(SnippetVaultIcon), category: "Productivity" },
|
| 29 |
+
{ id: "dev-notes-sticky-panel", name: "Dev Notes Sticky Panel", description: "Sticky notes with AI summarization.", icon: React.createElement(DevNotesIcon), category: "Productivity" },
|
| 30 |
+
{ id: "ai-unit-test-generator", name: "AI Unit Test Generator", description: "Generate unit tests from source code.", icon: React.createElement(UnitTestGeneratorIcon), category: "AI Tools" },
|
| 31 |
+
{ id: "ai-commit-generator", name: "AI Commit Message Generator", description: "Smart, conventional commits via AI.", icon: React.createElement(CommitGeneratorIcon), category: "AI Tools" },
|
| 32 |
+
{ id: "visual-git-tree", name: "Visual Git Tree", description: "Visually trace your git commit history with an interactive graph and an AI-powered summary.", icon: React.createElement(GitLogAnalyzerIcon), category: "Git" },
|
| 33 |
+
{ id: "worker-thread-debugger", name: "AI Concurrency Analyzer", description: "Analyze JS for Web Worker issues like race conditions.", icon: React.createElement(ConcurrencyAnalyzerIcon), category: "Testing" },
|
| 34 |
+
{ id: "regex-sandbox", name: "RegEx Sandbox", description: "Visually test regular expressions, generate them with AI, and inspect match groups.", icon: React.createElement(RegexSandboxIcon), category: "Testing" },
|
| 35 |
+
{ id: "prompt-craft-pad", name: "Prompt Craft Pad", description: "Save, edit, and manage your custom AI prompts with variable testing.", icon: React.createElement(PromptCraftPadIcon), category: "AI Tools" },
|
| 36 |
+
{ id: "linter-formatter", name: "AI Code Formatter", description: "AI-powered, real-time code formatting.", icon: React.createElement(CodeFormatterIcon), category: "Core" },
|
| 37 |
+
{ id: "json-tree-navigator", name: "JSON Tree Navigator", description: "Navigate large JSON objects as a collapsible tree.", icon: React.createElement(JsonTreeIcon), category: "Core" },
|
| 38 |
+
{ id: "xbrl-converter", name: "XBRL Converter", description: "Convert JSON data to a simplified XBRL-like XML format using AI.", icon: React.createElement(XbrlConverterIcon), category: "Data" },
|
| 39 |
+
{ id: "css-grid-editor", name: "CSS Grid Visual Editor", description: "Drag-based layout builder for CSS Grid.", icon: React.createElement(CssGridEditorIcon), category: "Frontend" },
|
| 40 |
+
{ id: "schema-designer", name: "Schema Designer", description: "Visually design a database schema with a drag-and-drop interface and SQL export.", icon: React.createElement(SchemaDesignerIcon), category: "Database" },
|
| 41 |
+
{ id: "pwa-manifest-editor", name: "PWA Manifest Editor", description: "Configure and preview Progressive Web App manifests with a home screen simulator.", icon: React.createElement(PwaManifestEditorIcon), category: "Frontend" },
|
| 42 |
+
{ id: "markdown-slides-generator", name: "Markdown Slides", description: "Turn markdown into a fullscreen presentation with an interactive overlay.", icon: React.createElement(MarkdownSlidesIcon), category: "Productivity" },
|
| 43 |
+
{ id: "screenshot-to-component", name: "Screenshot-to-Component", description: "Turn UI screenshots into functional code via paste or upload.", icon: React.createElement(ScreenshotToComponentIcon), category: "AI Tools" },
|
| 44 |
+
{ id: "font-preview-picker", name: "Font Preview & Picker", description: "Preview fonts and get CSS import rules.", icon: React.createElement(FontPreviewIcon), category: "Frontend" },
|
| 45 |
+
{ id: "svg-path-editor", name: "SVG Path Editor", description: "Visually create and manipulate SVG path data with an interactive canvas.", icon: React.createElement(SvgPathEditorIcon), category: "Frontend" },
|
| 46 |
+
{ id: "ai-style-transfer", name: "AI Code Style Transfer", description: "Rewrite code to match a specific style guide.", icon: React.createElement(StyleTransferIcon), category: "AI Tools" },
|
| 47 |
+
{ id: "ai-coding-challenge", name: "AI Coding Challenge Generator", description: "Generate unique coding exercises.", icon: React.createElement(CodingChallengeIcon), category: "AI Tools" },
|
| 48 |
+
{ id: "font-pairing-tool", name: "Font Pairing Tool", description: "Suggest and preview font combinations.", icon: React.createElement(FontPairingIcon), category: "Frontend" },
|
| 49 |
+
{ id: "code-review-bot", name: "AI Code Review Bot", description: "Get an automated code review from an AI.", icon: React.createElement(CodeReviewBotIcon), category: "AI Tools" },
|
| 50 |
+
{ id: "pr-summary-generator", name: "AI PR Summary Generator", description: "Generate a structured PR summary from code diffs, ready to copy as markdown.", icon: React.createElement(PrSummaryGeneratorIcon), category: "AI Tools" },
|
| 51 |
+
{ id: "changelog-generator", name: "AI Changelog Generator", description: "Auto-build changelogs from raw git logs.", icon: React.createElement(ChangelogGeneratorIcon), category: "Git" },
|
| 52 |
+
{ id: "cron-job-builder", name: "AI Cron Job Builder", description: "Visually tool to configure cron jobs, with AI.", icon: React.createElement(CronJobBuilderIcon), category: "Deployment" },
|
| 53 |
+
{ id: "project-moodboard", name: "Project Moodboard", description: "Organize ideas with interactive, multi-colored sticky notes.", icon: React.createElement(MoodboardIcon), category: "Productivity" },
|
| 54 |
+
{ id: "async-call-tree-viewer", name: "Async Call Tree Viewer", description: "Visualize a tree of asynchronous function calls from JSON data.", icon: React.createElement(AsyncCallTreeIcon), category: "Testing" },
|
| 55 |
+
{ id: "audio-to-code", name: "AI Audio-to-Code", description: "Speak your programming ideas and watch them turn into code.", icon: React.createElement(AudioToCodeIcon), category: "AI Tools" },
|
| 56 |
+
{ id: "code-diff-ghost", name: "Code Diff Ghost", description: "Visualize code changes with a 'ghost typing' effect.", icon: React.createElement(CodeDiffGhostIcon), category: "Git" },
|
| 57 |
+
{ id: "code-spell-checker", name: "Code Spell Checker", description: "A spell checker that finds common typos in code.", icon: React.createElement(CodeSpellCheckerIcon), category: "Testing" },
|
| 58 |
+
{ id: "color-palette-generator", name: "AI Color Palette Generator", description: "Pick a base color and let Gemini design a beautiful palette.", icon: React.createElement(ColorPaletteGeneratorIcon), category: "Frontend" },
|
| 59 |
+
{ id: "logic-flow-builder", name: "Logic Flow Builder", description: "A visual tool for building application logic flows.", icon: React.createElement(LogicFlowBuilderIcon), category: "Workflow" },
|
| 60 |
+
{ id: "meta-tag-editor", name: "Meta Tag Editor", description: "Generate SEO/social media meta tags with a live social card preview.", icon: React.createElement(MetaTagEditorIcon), category: "Frontend" },
|
| 61 |
+
{ id: "network-visualizer", name: "Network Visualizer", description: "Inspect network resources with a summary and visual waterfall chart.", icon: React.createElement(NetworkVisualizerIcon), category: "Testing" },
|
| 62 |
+
{ id: "pr-generator", name: "PR Generator", description: "Draft a professional pull request from a structured template.", icon: React.createElement(PrGeneratorIcon), category: "Git" },
|
| 63 |
+
{ id: "responsive-tester", name: "Responsive Tester", description: "Preview your web pages at different screen sizes and custom resolutions.", icon: React.createElement(ResponsiveTesterIcon), category: "Frontend" },
|
| 64 |
+
{ id: "sass-scss-compiler", name: "SASS/SCSS Compiler", description: "A real-time SASS/SCSS to CSS compiler.", icon: React.createElement(SassCompilerIcon), category: "Frontend" },
|
| 65 |
+
];
|
| 66 |
+
|
| 67 |
+
export const ALL_FEATURE_IDS = RAW_FEATURES.map(f => f.id);
|
globals.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// globals.d.ts
|
| 2 |
+
declare global {
|
| 3 |
+
/**
|
| 4 |
+
* Loads the Pyodide WebAssembly module.
|
| 5 |
+
* @param config Optional configuration for Pyodide.
|
| 6 |
+
*/
|
| 7 |
+
function loadPyodide(config?: { indexURL?: string }): Promise<any>;
|
| 8 |
+
|
| 9 |
+
interface Window {
|
| 10 |
+
google?: {
|
| 11 |
+
accounts: {
|
| 12 |
+
id: {
|
| 13 |
+
initialize: (config: { client_id: string; callback: (response: any) => void; }) => void;
|
| 14 |
+
renderButton: (parent: HTMLElement, options: any) => void;
|
| 15 |
+
disableAutoSelect: () => void;
|
| 16 |
+
prompt: () => void;
|
| 17 |
+
};
|
| 18 |
+
};
|
| 19 |
+
};
|
| 20 |
+
}
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
// This export statement is required to make the file a module.
|
| 24 |
+
export {};
|
index.css
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
@tailwind base;
|
| 2 |
+
@tailwind components;
|
| 3 |
+
@tailwind utilities;
|
| 4 |
+
|
| 5 |
+
/* Custom global styles */
|
| 6 |
+
body {
|
| 7 |
+
-webkit-font-smoothing: antialiased;
|
| 8 |
+
-moz-osx-font-smoothing: grayscale;
|
| 9 |
+
background-image: linear-gradient(135deg, #FFFFFF 0%, #F5F7FA 100%);
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
#root {
|
| 13 |
+
position: relative;
|
| 14 |
+
z-index: 1;
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
#root::before {
|
| 18 |
+
content: 'CitiBank demo business inc';
|
| 19 |
+
position: fixed;
|
| 20 |
+
top: 50%;
|
| 21 |
+
left: 50%;
|
| 22 |
+
transform: translate(-50%, -50%) rotate(-30deg);
|
| 23 |
+
font-family: theme('fontFamily.serif');
|
| 24 |
+
font-size: clamp(2rem, 8vw, 6rem); /* Responsive font size */
|
| 25 |
+
font-weight: bold;
|
| 26 |
+
color: theme('colors.gold');
|
| 27 |
+
opacity: 0.08;
|
| 28 |
+
pointer-events: none;
|
| 29 |
+
z-index: -1;
|
| 30 |
+
white-space: nowrap;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
h1, h2, h3, h4, h5, h6 {
|
| 34 |
+
@apply font-serif text-text-primary;
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
h1 {
|
| 38 |
+
@apply text-text-primary;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
/* Update primary buttons for a professional look */
|
| 42 |
+
.btn-primary {
|
| 43 |
+
@apply bg-primary text-text-on-primary font-bold rounded-md hover:opacity-90 transition-all disabled:opacity-50 shadow-md;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
/* Custom scrollbars for the new light theme */
|
| 47 |
+
::-webkit-scrollbar {
|
| 48 |
+
width: 8px;
|
| 49 |
+
height: 8px;
|
| 50 |
+
}
|
| 51 |
+
::-webkit-scrollbar-track {
|
| 52 |
+
@apply bg-gray-100;
|
| 53 |
+
}
|
| 54 |
+
::-webkit-scrollbar-thumb {
|
| 55 |
+
@apply bg-gray-400 rounded;
|
| 56 |
+
}
|
| 57 |
+
::-webkit-scrollbar-thumb:hover {
|
| 58 |
+
@apply bg-gray-500;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
/* Base transitions for interactive elements */
|
| 62 |
+
button, a, input, textarea, select {
|
| 63 |
+
transition: all 0.2s ease-in-out;
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
/* Keyframe Animations */
|
| 67 |
+
@keyframes fadeIn {
|
| 68 |
+
from { opacity: 0; }
|
| 69 |
+
to { opacity: 1; }
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
@keyframes shake {
|
| 73 |
+
10%, 90% { transform: translateX(-1px); }
|
| 74 |
+
20%, 80% { transform: translateX(2px); }
|
| 75 |
+
30%, 50%, 70% { transform: translateX(-3px); }
|
| 76 |
+
40%, 60% { transform: translateX(3px); }
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
@keyframes pop-in {
|
| 80 |
+
from {
|
| 81 |
+
opacity: 0;
|
| 82 |
+
transform: scale(0.95) translateY(10px);
|
| 83 |
+
}
|
| 84 |
+
to {
|
| 85 |
+
opacity: 1;
|
| 86 |
+
transform: scale(1) translateY(0);
|
| 87 |
+
}
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
.fade-in { animation: fadeIn 0.5s ease-in-out forwards; }
|
| 91 |
+
.animate-shake { animation: shake 0.4s ease-in-out; }
|
| 92 |
+
.animate-pop-in { animation: pop-in 0.3s ease-out forwards; }
|
| 93 |
+
|
| 94 |
+
/* For hiding scrollbar but keeping functionality */
|
| 95 |
+
.no-scrollbar::-webkit-scrollbar { display: none; }
|
| 96 |
+
.no-scrollbar {
|
| 97 |
+
-ms-overflow-style: none;
|
| 98 |
+
scrollbar-width: none;
|
| 99 |
+
scroll-behavior: smooth;
|
| 100 |
+
}
|
index.html
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8" />
|
| 5 |
+
<link rel="icon" type="image/svg+xml" href="./vite.svg" />
|
| 6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
| 7 |
+
<title>DevCore AI Toolkit</title>
|
| 8 |
+
|
| 9 |
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
| 10 |
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
| 11 |
+
<link href="https://fonts.googleapis.com/css2?family=EB+Garamond:wght@700&family=Inter:wght@400;500;700&family=Great+Vibes&display=swap" rel="stylesheet">
|
| 12 |
+
<script src="https://accounts.google.com/gsi/client" async defer></script>
|
| 13 |
+
<script type="importmap">
|
| 14 |
+
{
|
| 15 |
+
"imports": {
|
| 16 |
+
"react": "https://esm.sh/react@^19.1.1",
|
| 17 |
+
"react-dom/": "https://esm.sh/react-dom@^19.1.1/",
|
| 18 |
+
"react/": "https://esm.sh/react@^19.1.1/",
|
| 19 |
+
"path": "https://esm.sh/path@^0.12.7",
|
| 20 |
+
"vite": "https://esm.sh/vite@^7.1.1",
|
| 21 |
+
"url": "https://esm.sh/url@^0.11.4",
|
| 22 |
+
"@google/genai": "https://esm.sh/@google/genai@^1.13.0",
|
| 23 |
+
"marked": "https://esm.sh/marked@^16.1.2",
|
| 24 |
+
"diff": "https://esm.sh/diff@^8.0.2",
|
| 25 |
+
"react-colorful": "https://esm.sh/react-colorful@^5.6.1",
|
| 26 |
+
"idb": "https://esm.sh/idb@^8.0.3",
|
| 27 |
+
"jszip": "https://esm.sh/jszip@^3.10.1"
|
| 28 |
+
}
|
| 29 |
+
}
|
| 30 |
+
</script>
|
| 31 |
+
<link rel="stylesheet" href="/index.css">
|
| 32 |
+
</head>
|
| 33 |
+
<body class="bg-background text-text-primary font-sans">
|
| 34 |
+
<div id="root"></div>
|
| 35 |
+
<script type="module" src="./index.tsx"></script>
|
| 36 |
+
<script type="module" src="/index.tsx"></script>
|
| 37 |
+
</body>
|
| 38 |
+
</html>
|
index.tsx
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* @license
|
| 3 |
+
* SPDX-License-Identifier: Apache-2.0
|
| 4 |
+
*/
|
| 5 |
+
|
| 6 |
+
import React from 'react';
|
| 7 |
+
import ReactDOM from 'react-dom/client';
|
| 8 |
+
import App from './App.tsx';
|
| 9 |
+
import { GlobalStateProvider } from './contexts/GlobalStateContext.tsx';
|
| 10 |
+
import './index.css';
|
| 11 |
+
|
| 12 |
+
const rootElement = document.getElementById('root');
|
| 13 |
+
if (!rootElement) {
|
| 14 |
+
throw new Error("Could not find root element to mount to");
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
const root = ReactDOM.createRoot(rootElement);
|
| 18 |
+
root.render(
|
| 19 |
+
<React.StrictMode>
|
| 20 |
+
<GlobalStateProvider>
|
| 21 |
+
<App />
|
| 22 |
+
</GlobalStateProvider>
|
| 23 |
+
</React.StrictMode>
|
| 24 |
+
);
|
metadata.json
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"requestFramePermissions": [
|
| 3 |
+
"microphone"
|
| 4 |
+
],
|
| 5 |
+
"name": "0",
|
| 6 |
+
"description": "",
|
| 7 |
+
"prompt": ""
|
| 8 |
+
}
|
package-lock.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "devcore-ai-toolkit",
|
| 3 |
+
"private": true,
|
| 4 |
+
"version": "0.0.0",
|
| 5 |
+
"type": "module",
|
| 6 |
+
"scripts": {
|
| 7 |
+
"dev": "vite",
|
| 8 |
+
"build": "vite build",
|
| 9 |
+
"preview": "vite preview"
|
| 10 |
+
},
|
| 11 |
+
"dependencies": {
|
| 12 |
+
"@google/genai": "^1.12.0",
|
| 13 |
+
"diff": "^5.2.0",
|
| 14 |
+
"idb": "^8.0.0",
|
| 15 |
+
"jszip": "^3.10.1",
|
| 16 |
+
"marked": "^13.0.2",
|
| 17 |
+
"react": "^18.2.0",
|
| 18 |
+
"react-colorful": "^5.6.1",
|
| 19 |
+
"react-dom": "^18.2.0"
|
| 20 |
+
},
|
| 21 |
+
"devDependencies": {
|
| 22 |
+
"@types/diff": "^5.2.1",
|
| 23 |
+
"@types/jszip": "^3.4.1",
|
| 24 |
+
"@types/marked": "^6.0.0",
|
| 25 |
+
"@types/node": "^20.14.9",
|
| 26 |
+
"@types/react": "^18.2.0",
|
| 27 |
+
"@types/react-dom": "^18.2.0",
|
| 28 |
+
"autoprefixer": "^10.4.19",
|
| 29 |
+
"postcss": "^8.4.38",
|
| 30 |
+
"tailwindcss": "^3.4.3",
|
| 31 |
+
"typescript": "^5.5.2",
|
| 32 |
+
"vite": "^5.2.0"
|
| 33 |
+
}
|
| 34 |
+
}
|
postcss.config.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export default {
|
| 2 |
+
plugins: {
|
| 3 |
+
tailwindcss: {},
|
| 4 |
+
autoprefixer: {},
|
| 5 |
+
},
|
| 6 |
+
}
|
services
ADDED
|
File without changes
|
tailwind.config.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/** @type {import('tailwindcss').Config} */
|
| 2 |
+
export default {
|
| 3 |
+
content: [
|
| 4 |
+
"./index.html",
|
| 5 |
+
"./**/*.{js,ts,jsx,tsx}",
|
| 6 |
+
],
|
| 7 |
+
theme: {
|
| 8 |
+
extend: {
|
| 9 |
+
fontFamily: {
|
| 10 |
+
sans: ['Inter', 'sans-serif'],
|
| 11 |
+
serif: ['"EB Garamond"', 'serif'],
|
| 12 |
+
calligraphy: ['"Great Vibes"', 'cursive'],
|
| 13 |
+
},
|
| 14 |
+
colors: {
|
| 15 |
+
'primary': '#0047AB', // Cobalt Blue
|
| 16 |
+
'background': '#F5F7FA', // Light silver-blue
|
| 17 |
+
'surface': '#FFFFFF',
|
| 18 |
+
'text': {
|
| 19 |
+
'primary': '#111827', // Gray 900
|
| 20 |
+
'secondary': '#6B7280', // Gray 500
|
| 21 |
+
'on-primary': '#FFFFFF',
|
| 22 |
+
},
|
| 23 |
+
'border': '#E5E7EB', // Gray 200
|
| 24 |
+
'gold': '#B8860B', // DarkGoldenRod - better for watermark
|
| 25 |
+
},
|
| 26 |
+
boxShadow: {
|
| 27 |
+
'focus-primary': '0 0 0 3px rgba(0, 71, 171, 0.4)',
|
| 28 |
+
'md': '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)',
|
| 29 |
+
},
|
| 30 |
+
},
|
| 31 |
+
},
|
| 32 |
+
plugins: [],
|
| 33 |
+
}
|
tsconfig.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
{
|
| 3 |
+
"compilerOptions": {
|
| 4 |
+
"target": "ES2022",
|
| 5 |
+
"experimentalDecorators": true,
|
| 6 |
+
"useDefineForClassFields": false,
|
| 7 |
+
"module": "ES2022",
|
| 8 |
+
"lib": [
|
| 9 |
+
"ES2022",
|
| 10 |
+
"DOM",
|
| 11 |
+
"DOM.Iterable"
|
| 12 |
+
],
|
| 13 |
+
"skipLibCheck": true,
|
| 14 |
+
"moduleResolution": "bundler",
|
| 15 |
+
"isolatedModules": true,
|
| 16 |
+
"moduleDetection": "force",
|
| 17 |
+
"allowJs": true,
|
| 18 |
+
"jsx": "react-jsx",
|
| 19 |
+
"paths": {
|
| 20 |
+
"@/*": [
|
| 21 |
+
"./*"
|
| 22 |
+
]
|
| 23 |
+
},
|
| 24 |
+
"allowImportingTsExtensions": true,
|
| 25 |
+
"noEmit": true
|
| 26 |
+
}
|
| 27 |
+
}
|
tsconfig.server.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
{
|
| 3 |
+
"compilerOptions": {
|
| 4 |
+
"target": "ES2022",
|
| 5 |
+
"module": "CommonJS",
|
| 6 |
+
"moduleResolution": "node",
|
| 7 |
+
"outDir": "./hf-api",
|
| 8 |
+
"esModuleInterop": true,
|
| 9 |
+
"forceConsistentCasingInFileNames": true,
|
| 10 |
+
"strict": true,
|
| 11 |
+
"skipLibCheck": true
|
| 12 |
+
},
|
| 13 |
+
"include": [
|
| 14 |
+
"hf-api/server.ts"
|
| 15 |
+
]
|
| 16 |
+
}
|
types.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import type React from 'react';
|
| 2 |
+
import { CHROME_VIEW_IDS } from './constants.ts';
|
| 3 |
+
|
| 4 |
+
export type ChromeViewType = typeof CHROME_VIEW_IDS[number];
|
| 5 |
+
export type FeatureId = string;
|
| 6 |
+
|
| 7 |
+
export interface Feature {
|
| 8 |
+
id: FeatureId;
|
| 9 |
+
name: string;
|
| 10 |
+
description: string;
|
| 11 |
+
icon: React.ReactNode;
|
| 12 |
+
category: string;
|
| 13 |
+
component: React.FC<any>;
|
| 14 |
+
aiConfig?: {
|
| 15 |
+
model: string;
|
| 16 |
+
systemInstruction?: string;
|
| 17 |
+
};
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
export type ViewType = FeatureId | ChromeViewType;
|
| 21 |
+
|
| 22 |
+
export interface GeneratedFile {
|
| 23 |
+
filePath: string;
|
| 24 |
+
content: string;
|
| 25 |
+
description: string;
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
export interface SidebarItem {
|
| 29 |
+
id: string;
|
| 30 |
+
label: string;
|
| 31 |
+
icon: React.ReactNode;
|
| 32 |
+
view: ViewType;
|
| 33 |
+
props?: any;
|
| 34 |
+
action?: () => void;
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
export interface StructuredPrSummary {
|
| 38 |
+
title: string;
|
| 39 |
+
summary: string;
|
| 40 |
+
changes: string[];
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
export interface User {
|
| 44 |
+
name: string;
|
| 45 |
+
email: string;
|
| 46 |
+
picture: string;
|
| 47 |
+
}
|
vite.config.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
import path from 'path';
|
| 3 |
+
import { defineConfig, loadEnv } from 'vite';
|
| 4 |
+
import { fileURLToPath } from 'url';
|
| 5 |
+
|
| 6 |
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
| 7 |
+
|
| 8 |
+
export default defineConfig(({ mode }) => {
|
| 9 |
+
const env = loadEnv(mode, '.', '');
|
| 10 |
+
|
| 11 |
+
return {
|
| 12 |
+
define: {
|
| 13 |
+
// The API key is injected into the app during the build process.
|
| 14 |
+
// It's crucial that this variable is set in your deployment environment.
|
| 15 |
+
'process.env.GEMINI_API_KEY': JSON.stringify(env.GEMINI_API_KEY)
|
| 16 |
+
},
|
| 17 |
+
resolve: {
|
| 18 |
+
alias: {
|
| 19 |
+
'@': path.resolve(__dirname, '.'),
|
| 20 |
+
}
|
| 21 |
+
},
|
| 22 |
+
build: {
|
| 23 |
+
outDir: 'web', // Emit assets to a 'web' directory.
|
| 24 |
+
sourcemap: true, // Enable source maps for easier debugging in production.
|
| 25 |
+
rollupOptions: {
|
| 26 |
+
output: {
|
| 27 |
+
// Improve caching by splitting vendor code into separate chunks.
|
| 28 |
+
manualChunks(id) {
|
| 29 |
+
if (id.includes('node_modules')) {
|
| 30 |
+
return id.toString().split('node_modules/')[1].split('/')[0].toString();
|
| 31 |
+
}
|
| 32 |
+
}
|
| 33 |
+
}
|
| 34 |
+
}
|
| 35 |
+
}
|
| 36 |
+
};
|
| 37 |
+
});
|