Skip to content

Commit 764a773

Browse files
committed
v2.1 Alpha
2 parents 444d7d0 + 9ed6e1c commit 764a773

53 files changed

Lines changed: 5284 additions & 518 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/deploy.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Simple workflow for deploying static content to GitHub Pages
2+
name: Deploy static content to Pages
3+
4+
on:
5+
# Runs on pushes targeting the default branch
6+
push:
7+
branches: ['main']
8+
9+
# Allows you to run this workflow manually from the Actions tab
10+
workflow_dispatch:
11+
12+
# Sets the GITHUB_TOKEN permissions to allow deployment to GitHub Pages
13+
permissions:
14+
contents: read
15+
pages: write
16+
id-token: write
17+
18+
# Allow one concurrent deployment
19+
concurrency:
20+
group: 'pages'
21+
cancel-in-progress: true
22+
23+
jobs:
24+
# Single deploy job since we're just deploying
25+
deploy:
26+
environment:
27+
name: github-pages
28+
url: ${{ steps.deployment.outputs.page_url }}
29+
runs-on: ubuntu-latest
30+
steps:
31+
- name: Checkout
32+
uses: actions/checkout@v5
33+
- name: Set up Node
34+
uses: actions/setup-node@v6
35+
with:
36+
node-version: lts/*
37+
cache: 'npm'
38+
- name: Install dependencies
39+
run: npm ci
40+
- name: Build
41+
run: npm run build
42+
- name: Setup Pages
43+
uses: actions/configure-pages@v5
44+
- name: Upload artifact
45+
uses: actions/upload-pages-artifact@v4
46+
with:
47+
# Upload dist folder
48+
path: './dist'
49+
- name: Deploy to GitHub Pages
50+
id: deployment
51+
uses: actions/deploy-pages@v4

.gitignore

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
!.vscode/extensions.json
18+
.idea
19+
.DS_Store
20+
*.suo
21+
*.ntvs*
22+
*.njsproj
23+
*.sln
24+
*.sw?
25+
26+
.vite

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,4 @@ Run small LLMs directly on your device, no cloud computing needed.
33

44
* *The bigger the model, the better the performance*
55

6-
<a href="https://nirgranthi.github.io/local-slave" target="_blank">
7-
<img src="https://img.shields.io/badge/🚀_Live_Demo-Start_Here-3b82f6?style=for-the-badge&logo=github&logoColor=white" alt="Live Demo" height="40" />
8-
</a>
6+
[![Live Demo](https://img.shields.io/badge/🚀_Live_Demo-Start_Here-3b82f6?style=for-the-badge&logo=github&logoColor=white)](https://nirgranthi.github.io/local-slave/)

eslint.config.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import js from '@eslint/js'
2+
import globals from 'globals'
3+
import reactHooks from 'eslint-plugin-react-hooks'
4+
import reactRefresh from 'eslint-plugin-react-refresh'
5+
import { defineConfig, globalIgnores } from 'eslint/config'
6+
7+
export default defineConfig([
8+
globalIgnores(['dist']),
9+
{
10+
files: ['**/*.{js,jsx}'],
11+
extends: [
12+
js.configs.recommended,
13+
reactHooks.configs.flat.recommended,
14+
reactRefresh.configs.vite,
15+
],
16+
languageOptions: {
17+
ecmaVersion: 2020,
18+
globals: globals.browser,
19+
parserOptions: {
20+
ecmaVersion: 'latest',
21+
ecmaFeatures: { jsx: true },
22+
sourceType: 'module',
23+
},
24+
},
25+
rules: {
26+
'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }],
27+
},
28+
},
29+
])

index.html

Lines changed: 10 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -1,135 +1,13 @@
1-
<!DOCTYPE html>
1+
<!doctype html>
22
<html lang="en">
3-
<head>
4-
<meta charset="UTF-8">
3+
<head>
4+
<meta charset="UTF-8" />
55
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
66
<title>Your Local AI</title>
7-
<script src="https://cdn.tailwindcss.com"></script>
8-
<style>
9-
.no-scrollbar::-webkit-scrollbar { display: none; }
10-
.no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
11-
.sidebar-transition { transition: transform 0.3s ease-in-out; }
12-
.blink { animation: blinker 1.5s linear infinite; }
13-
@keyframes blinker { 50% { opacity: 0; } }
14-
.progress-bar { transition: width 0.3s ease; }
15-
.fade-in { animation: fadeIn 0.3s ease-in; }
16-
@keyframes fadeIn { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: translateY(0); } }
17-
</style>
18-
</head>
19-
<body class="bg-gray-900 text-white h-[100dvh] flex overflow-hidden">
20-
21-
<!-- Mobile Overlay -->
22-
<div id="backdrop" onclick="closeSidebar()" class="fixed inset-0 bg-black/60 z-40 hidden backdrop-blur-sm md:hidden"></div>
23-
24-
<!-- SIDEBAR -->
25-
<div id="sidebar" class="fixed inset-y-0 left-0 w-80 bg-gray-800 border-r border-gray-700 z-50 transform -translate-x-full md:translate-x-0 md:relative sidebar-transition flex flex-col shadow-2xl shrink-0">
26-
<!-- Tabs -->
27-
<div class="flex border-b border-gray-700">
28-
<button onclick="switchTab('models')" id="tab-models" class="flex-1 py-3 text-xs font-bold text-blue-400 border-b-2 border-blue-400 bg-gray-700/50">MODELS</button>
29-
<button onclick="switchTab('history')" id="tab-history" class="flex-1 py-3 text-xs font-bold text-gray-500 hover:text-gray-300">HISTORY</button>
30-
</div>
31-
32-
<div class="p-4 flex-1 overflow-y-auto space-y-6 no-scrollbar">
33-
34-
<!-- MODELS TAB -->
35-
<div id="view-models" class="space-y-6">
36-
<!-- CSV Models Section -->
37-
<div>
38-
<div class="flex justify-between items-center mb-2">
39-
<div class="text-xs text-gray-400 uppercase font-bold">Available Models</div>
40-
<button onclick="loadModelList()" class="text-[10px] text-blue-400 hover:underline">Refresh</button>
41-
</div>
42-
<div id="csv-model-list" class="space-y-2">
43-
<div class="text-xs text-gray-600 italic text-center py-4">Loading list...</div>
44-
</div>
45-
</div>
46-
47-
<!-- Manual Upload -->
48-
<div class="border-t border-gray-700 pt-4">
49-
<div class="text-xs text-gray-400 uppercase font-bold mb-2">Manual Upload</div>
50-
<label class="flex flex-col items-center justify-center w-full h-24 border-2 border-dashed border-gray-600 rounded-lg cursor-pointer hover:bg-gray-700 hover:border-blue-500 transition-colors bg-gray-800/50">
51-
<div class="flex flex-col items-center justify-center pt-2 pb-3">
52-
<svg class="w-6 h-6 mb-1 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"></path></svg>
53-
<p class="text-[10px] text-gray-400">Tap to Select .gguf</p>
54-
</div>
55-
<input type="file" id="file-upload" accept=".gguf" class="hidden" />
56-
</label>
57-
</div>
58-
</div>
59-
60-
<!-- HISTORY TAB -->
61-
<div id="view-history" class="hidden space-y-2">
62-
<div class="flex justify-between items-center mb-2">
63-
<div class="text-xs text-gray-400 uppercase font-bold">Recent Chats</div>
64-
<button onclick="clearAllHistory()" class="text-[10px] text-red-400 hover:underline">Clear All</button>
65-
</div>
66-
<div id="history-list" class="space-y-1">
67-
<!-- History Items Injected Here -->
68-
</div>
69-
</div>
70-
71-
<!-- Download Progress -->
72-
<div id="dl-progress-container" class="hidden bg-gray-900 rounded-lg p-3 border border-gray-700 mt-auto">
73-
<div class="flex justify-between text-[10px] mb-1">
74-
<span class="text-blue-300">Downloading...</span>
75-
<span id="dl-percent" class="text-white font-mono">0%</span>
76-
</div>
77-
<div class="w-full bg-gray-700 rounded-full h-1.5">
78-
<div id="dl-bar" class="bg-blue-500 h-1.5 rounded-full progress-bar" style="width: 0%"></div>
79-
</div>
80-
<div id="dl-details" class="text-[9px] text-gray-500 mt-1 text-right font-mono">0MB / 0MB</div>
81-
</div>
82-
</div>
83-
84-
<div class="p-2 text-center text-[10px] text-gray-600 bg-gray-800 border-t border-gray-700">v1.17.3 (Input Fixes)</div>
85-
</div>
86-
87-
<!-- MAIN CHAT -->
88-
<div class="flex-1 flex flex-col relative w-full bg-gray-900 min-w-0">
89-
<!-- Header -->
90-
<div class="h-14 border-b border-gray-700 flex items-center px-4 justify-between bg-gray-800 z-10">
91-
<div class="flex items-center gap-3">
92-
<button onclick="openSidebar()" class="md:hidden text-gray-400 p-1 hover:text-white">
93-
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path></svg>
94-
</button>
95-
<div class="flex flex-col">
96-
<span id="header-status" class="font-bold text-sm text-gray-200">Local AI</span>
97-
<span id="active-model-name" class="text-[10px] text-gray-500 truncate max-w-[150px]">No Model Loaded</span>
98-
</div>
99-
</div>
100-
101-
<div class="flex items-center gap-2">
102-
<div id="engine-state" class="text-[10px] px-2 py-1 rounded bg-black/40 text-gray-400 font-mono hidden md:block">OFFLINE</div>
103-
<button onclick="startNewChat()" class="bg-blue-600 hover:bg-blue-500 text-white text-xs px-3 py-1.5 rounded-lg flex items-center gap-1 transition-colors">
104-
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path></svg>
105-
New Chat
106-
</button>
107-
</div>
108-
</div>
109-
110-
<!-- Chat Area -->
111-
<div id="chat-box" class="flex-1 overflow-y-auto p-4 pb-40 space-y-4">
112-
<div id="welcome-message" class="flex flex-col items-center justify-center h-full text-gray-500 space-y-4">
113-
<div class="p-4 bg-gray-800 rounded-full animate-bounce">
114-
<svg class="w-8 h-8 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path></svg>
115-
</div>
116-
<div class="text-center">
117-
<h3 class="text-lg font-medium text-white">How can I help you today?</h3>
118-
<p class="text-xs mt-1">Checking for downloaded models...</p>
119-
</div>
120-
</div>
121-
</div>
122-
123-
<!-- Input -->
124-
<div class="absolute bottom-0 w-full bg-gray-900 pt-4 pb-4 px-4 border-t border-gray-800">
125-
<div class="max-w-3xl mx-auto relative flex gap-2">
126-
<input id="user-input" type="text" class="flex-1 bg-gray-800 text-white rounded-lg px-4 py-3 border border-gray-700 focus:outline-none focus:border-blue-500 transition-all" placeholder="Load a model to start..." disabled>
127-
<button id="send-btn" onclick="sendMessage()" class="bg-blue-600 px-6 rounded-lg text-white font-medium disabled:opacity-50 disabled:cursor-not-allowed hover:bg-blue-700 transition-colors" disabled>Send</button>
128-
</div>
129-
</div>
130-
</div>
131-
132-
<script type="module" src="index.js">
133-
</script>
134-
</body>
135-
</html>
7+
<link rel="icon" type="image/svg+xml" href="/logo.png" />
8+
</head>
9+
<body>
10+
<div id="root"></div>
11+
<script type="module" src="/src/main.jsx"></script>
12+
</body>
13+
</html>

0 commit comments

Comments
 (0)