Use single server

This commit is contained in:
Jeffrey Morgan 2023-06-23 15:04:38 -04:00
parent ebec1c61db
commit 32c6d8e6cc
31 changed files with 9698 additions and 7799 deletions

View file

@ -1,6 +0,0 @@
# build the client
# build the go app
# build the desktop app

View file

@ -1,3 +1,16 @@
{ {
"extends": "next/core-web-vitals" "env": {
"browser": true,
"es6": true,
"node": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:import/recommended",
"plugin:import/electron",
"plugin:import/typescript"
],
"parser": "@typescript-eslint/parser"
} }

113
client/.gitignore vendored
View file

@ -1,35 +1,92 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # Logs
logs
# dependencies *.log
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*
yarn-error.log* yarn-error.log*
lerna-debug.log*
# local env files # Diagnostic reports (https://nodejs.org/api/report.html)
.env*.local report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# vercel # Runtime data
.vercel pids
*.pid
*.seed
*.pid.lock
.DS_Store
# typescript # Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo *.tsbuildinfo
next-env.d.ts
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# Webpack
.webpack/
# Vite
.vite/
# Electron-Forge
out/

View file

@ -1,34 +0,0 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

View file

@ -1,31 +0,0 @@
import { Metadata } from 'next'
import '@/app/globals.css'
export const metadata: Metadata = {
title: {
default: 'Keypair',
template: `%s - Keypair`,
},
themeColor: [
{ media: '(prefers-color-scheme: light)', color: 'white' },
{ media: '(prefers-color-scheme: dark)', color: 'black' },
],
icons: {
icon: '/favicon.ico',
shortcut: '/favicon-16x16.png',
apple: '/apple-touch-icon.png',
},
}
interface RootLayoutProps {
children: React.ReactNode
}
export default function RootLayout({ children }: RootLayoutProps) {
return (
<html lang='en' suppressHydrationWarning>
<body className='flex min-h-screen w-full bg-white font-sans antialiased'>{children}</body>
</html>
)
}

40
client/forge.config.ts Normal file
View file

@ -0,0 +1,40 @@
import type { ForgeConfig } from '@electron-forge/shared-types'
import { MakerSquirrel } from '@electron-forge/maker-squirrel'
import { MakerZIP } from '@electron-forge/maker-zip'
import { MakerDeb } from '@electron-forge/maker-deb'
import { MakerRpm } from '@electron-forge/maker-rpm'
import { AutoUnpackNativesPlugin } from '@electron-forge/plugin-auto-unpack-natives'
import { WebpackPlugin } from '@electron-forge/plugin-webpack'
import { mainConfig } from './webpack.main.config'
import { rendererConfig } from './webpack.renderer.config'
const config: ForgeConfig = {
packagerConfig: {
asar: true,
},
rebuildConfig: {},
makers: [new MakerSquirrel({}), new MakerZIP({}, ['darwin']), new MakerRpm({}), new MakerDeb({})],
plugins: [
new AutoUnpackNativesPlugin({}),
new WebpackPlugin({
mainConfig,
devContentSecurityPolicy: `default-src * 'unsafe-eval' 'unsafe-inline'`,
renderer: {
config: rendererConfig,
entryPoints: [
{
html: './src/index.html',
js: './src/renderer.tsx',
name: 'main_window',
preload: {
js: './src/preload.ts',
},
},
],
},
}),
],
}
export default config

View file

@ -1,5 +0,0 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

View file

@ -1,4 +0,0 @@
/** @type {import('next').NextConfig} */
const nextConfig = {}
module.exports = nextConfig

10799
client/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,40 +1,61 @@
{ {
"name": "client", "name": "client",
"version": "0.1.0", "productName": "client",
"private": true, "version": "1.0.0",
"description": "Proto",
"main": ".webpack/main",
"scripts": { "scripts": {
"dev": "next dev", "start": "electron-forge start",
"build": "next build", "package": "electron-forge package",
"start": "next start", "make": "electron-forge make",
"lint": "next lint", "publish": "electron-forge publish",
"package": "next build && pkg --target latest server.js" "lint": "eslint --ext .ts,.tsx ."
}, },
"pkg": { "keywords": [],
"assets": [ "author": {
".next/**/*", "name": "Jeffrey Morgan",
"static/**/*" "email": "jmorganca@gmail.com"
], },
"scripts": [ "license": "MIT",
".next/**/*.js" "devDependencies": {
] "@babel/core": "^7.22.5",
"@babel/preset-react": "^7.22.5",
"@electron-forge/cli": "^6.2.1",
"@electron-forge/maker-deb": "^6.2.1",
"@electron-forge/maker-rpm": "^6.2.1",
"@electron-forge/maker-squirrel": "^6.2.1",
"@electron-forge/maker-zip": "^6.2.1",
"@electron-forge/plugin-auto-unpack-natives": "^6.2.1",
"@electron-forge/plugin-webpack": "^6.2.1",
"@types/react": "^18.2.14",
"@types/react-dom": "^18.2.6",
"@typescript-eslint/eslint-plugin": "^5.60.0",
"@typescript-eslint/parser": "^5.60.0",
"@vercel/webpack-asset-relocator-loader": "^1.7.3",
"babel-loader": "^9.1.2",
"css-loader": "^6.8.1",
"electron": "25.2.0",
"eslint": "^8.43.0",
"eslint-plugin-import": "^2.27.5",
"fork-ts-checker-webpack-plugin": "^7.3.0",
"node-loader": "^2.0.0",
"postcss": "^8.4.24",
"postcss-import": "^15.1.0",
"postcss-loader": "^7.3.3",
"postcss-preset-env": "^8.5.1",
"style-loader": "^3.3.3",
"tailwindcss": "^3.3.2",
"ts-loader": "^9.4.3",
"ts-node": "^10.9.1",
"typescript": "~4.5.4",
"webpack": "^5.88.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1"
}, },
"dependencies": { "dependencies": {
"next": "13.4.7", "@types/node": "^20.3.1",
"react": "18.2.0", "electron-squirrel-startup": "^1.0.0",
"react-dom": "18.2.0" "react": "^18.2.0",
}, "react-dom": "^18.2.0"
"devDependencies": {
"@types/node": "20.3.1",
"@types/react": "18.2.13",
"@types/react-dom": "18.2.6",
"autoprefixer": "10.4.14",
"eslint": "8.43.0",
"eslint-config-next": "13.4.7",
"pkg": "^5.8.1",
"postcss": "8.4.24",
"prettier": "^2.8.8",
"prettier-plugin-tailwindcss": "^0.3.0",
"tailwindcss": "3.3.2",
"typescript": "5.1.3"
} }
} }

View file

@ -1,5 +1,6 @@
module.exports = { module.exports = {
plugins: { plugins: {
'postcss-import': {},
tailwindcss: {}, tailwindcss: {},
autoprefixer: {}, autoprefixer: {},
}, },

View file

@ -1,17 +0,0 @@
const { createServer } = require('http')
const { parse } = require('url')
const next = require('next')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare().then(() => {
createServer((req, res) => {
const parsedUrl = parse(req.url, true)
handle(req, res, parsedUrl)
}).listen(process.env.PORT || 3000, err => {
if (err) throw err
console.log('> Ready on http://localhost:3000')
})
})

View file

@ -8,5 +8,5 @@ body {
} }
.drag { .drag {
-webkit-app-region: drag; -webkit-app-region: deag;
} }

View file

@ -1,4 +1,3 @@
'use client'
import { useState } from 'react' import { useState } from 'react'
const API_URL = 'http://127.0.0.1:8080' const API_URL = 'http://127.0.0.1:8080'
@ -35,9 +34,10 @@ async function completion(prompt: string, callback: (res: string) => void) {
break break
} }
const t = Buffer.from(value).toString('utf8') let decoder = new TextDecoder()
if (t.startsWith('data: ')) { let str = decoder.decode(value)
const message = JSON.parse(t.substring(6)) if (str.startsWith('data: ')) {
const message = JSON.parse(str.substring(6))
callback(message.content) callback(message.content)
if (message.stop) { if (message.stop) {
break break
@ -48,12 +48,12 @@ async function completion(prompt: string, callback: (res: string) => void) {
return return
} }
export default function Home() { export default function () {
const [prompt, setPrompt] = useState('') const [prompt, setPrompt] = useState('')
const [messages, setMessages] = useState<Message[]>([]) const [messages, setMessages] = useState<Message[]>([])
return ( return (
<div className='flex min-h-screen flex-1 flex-col justify-between'> <div className='flex min-h-screen flex-1 flex-col justify-between bg-white'>
<header className='drag sticky top-0 z-50 flex w-full flex-row items-center border-b border-black/5 bg-gray-50/75 p-3 backdrop-blur-md'> <header className='drag sticky top-0 z-50 flex w-full flex-row items-center border-b border-black/5 bg-gray-50/75 p-3 backdrop-blur-md'>
<div className='mx-auto w-full max-w-xl leading-none'> <div className='mx-auto w-full max-w-xl leading-none'>
<h1 className='text-sm font-medium'>LLaMa</h1> <h1 className='text-sm font-medium'>LLaMa</h1>
@ -63,8 +63,8 @@ export default function Home() {
<section className='mx-auto mb-10 w-full max-w-xl flex-1 break-words'> <section className='mx-auto mb-10 w-full max-w-xl flex-1 break-words'>
{messages.map((m, i) => ( {messages.map((m, i) => (
<div className='my-4 flex gap-4' key={i}> <div className='my-4 flex gap-4' key={i}>
<div className='flex-none pr-2 text-lg'>{m.sender === 'human' ? '👩' : '🤖'}</div> <div className='flex-none pr-1 text-lg'>{m.sender === 'human' ? '👩' : '🤖'}</div>
<div className='flex-1 text-gray-900'> <div className='flex-1 text-gray-800'>
{m.content} {m.content}
{m.sender === 'bot' && <span className='relative -top-[3px] left-1 text-[10px] text-blue-600'></span>} {m.sender === 'bot' && <span className='relative -top-[3px] left-1 text-[10px] text-blue-600'></span>}
</div> </div>

9
client/src/index.html Normal file
View file

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<div id="app"></div>
</body>
</html>

View file

@ -1,12 +1,17 @@
const { app, BrowserWindow } = require('electron') import { app, BrowserWindow } from 'electron'
const path = require('path') // This allows TypeScript to pick up the magic constants that's auto-generated by Forge's Webpack
// plugin that tells the Electron app where to look for the Webpack-bundled app code (depending on
// whether you're running in development or production).
declare const MAIN_WINDOW_WEBPACK_ENTRY: string
declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: string
// Handle creating/removing shortcuts on Windows when installing/uninstalling. // Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) { if (require('electron-squirrel-startup')) {
app.quit() app.quit()
} }
const createWindow = () => { const createWindow = (): void => {
// Create the browser window.
// Create the browser window. // Create the browser window.
const mainWindow = new BrowserWindow({ const mainWindow = new BrowserWindow({
width: 800, width: 800,
@ -20,7 +25,7 @@ const createWindow = () => {
}) })
// and load the index.html of the app. // and load the index.html of the app.
mainWindow.loadURL('http://localhost:3000') mainWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY)
// Open the DevTools. // Open the DevTools.
mainWindow.webContents.openDevTools() mainWindow.webContents.openDevTools()

2
client/src/preload.ts Normal file
View file

@ -0,0 +1,2 @@
// See the Electron documentation for details on how to use preload scripts:
// https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts

7
client/src/renderer.tsx Normal file
View file

@ -0,0 +1,7 @@
import App from './app'
import './app.css'
import { createRoot } from 'react-dom/client'
const container = document.getElementById('app')
const root = createRoot(container)
root.render(<App />)

View file

@ -1,10 +1,6 @@
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
module.exports = { module.exports = {
content: [ content: ['./src/**/*.{js,ts,jsx,tsx,mdx}'],
'./pages/**/*.{js,ts,jsx,tsx,mdx}',
'./components/**/*.{js,ts,jsx,tsx,mdx}',
'./app/**/*.{js,ts,jsx,tsx,mdx}',
],
theme: {}, theme: {},
plugins: [], plugins: [],
} }

View file

@ -1,28 +1,20 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "ES6",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true, "allowJs": true,
"module": "commonjs",
"skipLibCheck": true, "skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true, "esModuleInterop": true,
"module": "esnext", "noImplicitAny": true,
"sourceMap": true,
"baseUrl": ".",
"outDir": "dist",
"moduleResolution": "node", "moduleResolution": "node",
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": { "paths": {
"@/*": ["./*"] "*": ["node_modules/*"]
} },
"jsx": "react-jsx"
}, },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], "include": ["src/**/*"]
"exclude": ["node_modules"]
} }

View file

@ -0,0 +1,18 @@
import type { Configuration } from 'webpack'
import { rules } from './webpack.rules'
export const mainConfig: Configuration = {
/**
* This is the main entry point for your application, it's the first file
* that runs in the main process.
*/
entry: './src/index.ts',
// Put your normal webpack config below here
module: {
rules,
},
resolve: {
extensions: ['.js', '.ts', '.jsx', '.tsx', '.css', '.json'],
},
}

10
client/webpack.plugins.ts Normal file
View file

@ -0,0 +1,10 @@
import type IForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const ForkTsCheckerWebpackPlugin: typeof IForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')
export const plugins = [
new ForkTsCheckerWebpackPlugin({
logger: 'webpack-infrastructure',
}),
]

View file

@ -0,0 +1,19 @@
import type { Configuration } from 'webpack'
import { rules } from './webpack.rules'
import { plugins } from './webpack.plugins'
rules.push({
test: /\.css$/,
use: [{ loader: 'style-loader' }, { loader: 'css-loader' }, { loader: 'postcss-loader' }],
})
export const rendererConfig: Configuration = {
module: {
rules,
},
plugins,
resolve: {
extensions: ['.js', '.ts', '.jsx', '.tsx', '.css'],
},
}

31
client/webpack.rules.ts Normal file
View file

@ -0,0 +1,31 @@
import type { ModuleOptions } from 'webpack'
export const rules: Required<ModuleOptions>['rules'] = [
// Add support for native node modules
{
// We're specifying native_modules in the test because the asset relocator loader generates a
// "fake" .node file which is really a cjs file.
test: /native_modules[/\\].+\.node$/,
use: 'node-loader',
},
{
test: /[/\\]node_modules[/\\].+\.(m?js|node)$/,
parser: { amd: false },
use: {
loader: '@vercel/webpack-asset-relocator-loader',
options: {
outputAssetBase: 'native_modules',
},
},
},
{
test: /\.tsx?$/,
exclude: /(node_modules|\.webpack)/,
use: {
loader: 'ts-loader',
options: {
transpileOnly: true,
},
},
},
]

92
desktop/.gitignore vendored
View file

@ -1,92 +0,0 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
.DS_Store
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# Webpack
.webpack/
# Vite
.vite/
# Electron-Forge
out/

View file

@ -1,30 +0,0 @@
module.exports = {
packagerConfig: {
asar: true,
},
rebuildConfig: {},
makers: [
{
name: '@electron-forge/maker-squirrel',
config: {},
},
{
name: '@electron-forge/maker-zip',
platforms: ['darwin'],
},
{
name: '@electron-forge/maker-deb',
config: {},
},
{
name: '@electron-forge/maker-rpm',
config: {},
},
],
plugins: [
{
name: '@electron-forge/plugin-auto-unpack-natives',
config: {},
},
],
}

6013
desktop/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,32 +0,0 @@
{
"name": "desktop",
"productName": "desktop",
"version": "1.0.0",
"description": "My Electron application description",
"main": "src/index.js",
"scripts": {
"start": "electron-forge start",
"package": "electron-forge package",
"make": "electron-forge make",
"publish": "electron-forge publish",
"lint": "echo \"No linting configured\""
},
"keywords": [],
"author": {
"name": "Jeffrey Morgan",
"email": "jeff@keypair.com"
},
"license": "MIT",
"dependencies": {
"electron-squirrel-startup": "^1.0.0"
},
"devDependencies": {
"@electron-forge/cli": "^6.2.1",
"@electron-forge/maker-deb": "^6.2.1",
"@electron-forge/maker-rpm": "^6.2.1",
"@electron-forge/maker-squirrel": "^6.2.1",
"@electron-forge/maker-zip": "^6.2.1",
"@electron-forge/plugin-auto-unpack-natives": "^6.2.1",
"electron": "25.1.1"
}
}

17
dev.sh
View file

@ -1,17 +0,0 @@
#!/bin/bash
# Function to handle Ctrl+C
handle_sigint() {
kill $pid1 $pid2
exit
}
# Trap Ctrl+C signal
trap 'handle_sigint' SIGINT
# Start three processes in the background
npm run dev --prefix ./client & pid1=$!
npm start --prefix ./desktop & pid2=$!
# Wait for all processes to finish
wait

View file

@ -1,2 +0,0 @@
npm install --prefix ./client
npm install --prefix ./desktop