Merge branch 'docs/pointing-client-remote-server' of https://github.com/janhq/jan into docs/pointing-client-remote-server

This commit is contained in:
Ho Duc Hieu 2024-01-03 15:24:19 +07:00
commit 455528de8d
12 changed files with 177 additions and 44 deletions

13
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,13 @@
## Describe Your Changes
-
## Fixes Issues
-
## Self Checklist
- [ ] Added relevant comments, esp in complex areas
- [ ] Updated docs (for bug fixes / features)
- [ ] Created issues for follow-up changes or refactoring needed

View File

@ -70,25 +70,25 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute
<tr style="text-align:center"> <tr style="text-align:center">
<td style="text-align:center"><b>Experimental (Nightly Build)</b></td> <td style="text-align:center"><b>Experimental (Nightly Build)</b></td>
<td style="text-align:center"> <td style="text-align:center">
<a href='https://delta.jan.ai/0.4.3-112/jan-win-x64-0.4.3-112.exe'> <a href='https://delta.jan.ai/0.4.3-117/jan-win-x64-0.4.3-117.exe'>
<img src='./docs/static/img/windows.png' style="height:14px; width: 14px" /> <img src='./docs/static/img/windows.png' style="height:14px; width: 14px" />
<b>jan.exe</b> <b>jan.exe</b>
</a> </a>
</td> </td>
<td style="text-align:center"> <td style="text-align:center">
<a href='https://delta.jan.ai/0.4.3-112/jan-mac-x64-0.4.3-112.dmg'> <a href='https://delta.jan.ai/0.4.3-117/jan-mac-x64-0.4.3-117.dmg'>
<img src='./docs/static/img/mac.png' style="height:15px; width: 15px" /> <img src='./docs/static/img/mac.png' style="height:15px; width: 15px" />
<b>Intel</b> <b>Intel</b>
</a> </a>
</td> </td>
<td style="text-align:center"> <td style="text-align:center">
<a href='https://delta.jan.ai/0.4.3-112/jan-mac-arm64-0.4.3-112.dmg'> <a href='https://delta.jan.ai/0.4.3-117/jan-mac-arm64-0.4.3-117.dmg'>
<img src='./docs/static/img/mac.png' style="height:15px; width: 15px" /> <img src='./docs/static/img/mac.png' style="height:15px; width: 15px" />
<b>M1/M2</b> <b>M1/M2</b>
</a> </a>
</td> </td>
<td style="text-align:center"> <td style="text-align:center">
<a href='https://delta.jan.ai/0.4.3-112/jan-linux-amd64-0.4.3-112.deb'> <a href='https://delta.jan.ai/0.4.3-117/jan-linux-amd64-0.4.3-117.deb'>
<img src='./docs/static/img/linux.png' style="height:14px; width: 14px" /> <img src='./docs/static/img/linux.png' style="height:14px; width: 14px" />
<b>jan.deb</b> <b>jan.deb</b>
</a> </a>

View File

@ -5,3 +5,4 @@ export * from './extension/store'
export * from './download' export * from './download'
export * from './module' export * from './module'
export * from './api' export * from './api'
export * from './log'

18
core/src/node/log.ts Normal file
View File

@ -0,0 +1,18 @@
import fs from 'fs'
import util from 'util'
import path from 'path'
import os from 'os'
const appDir = path.join(os.homedir(), 'jan')
export const logPath = path.join(appDir, 'app.log')
export const log = function (d: any) {
if (fs.existsSync(appDir)) {
var log_file = fs.createWriteStream(logPath, {
flags: 'a',
})
log_file.write(util.format(d) + '\n')
log_file.close()
}
}

View File

@ -3,4 +3,69 @@ title: Overview
slug: /docs slug: /docs
--- ---
Hello world The following low-level docs are aimed at core contributors and cover how to contribute to the Core SDK.
:::tip
If you are interested to **build on top of the SDK**, like creating assistants or adding app level extensions, please refer to [developer docs](/developer) instead.
:::
## Core SDK
At its Core, Jan is a cross-platform, local-first and AI native framework that can be used to build anything. In fact, current features are all implemented as 3rd party extensions on top of this Core SDK.
Ultimately, we aim for a VSCode or Obsidian like framework that allows devs to build and customize complex AI applications for their specific needs, in less than 15 minutes.
### Cross Platform
Jan follows [Clean Architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html) to the best of our ability. Though leaky abstractions remain (we're a fast moving, open source codebase), we do our best to build an SDK that allows devs to **build once, deploy everywhere.**
Currently, Jan supports:
- `Node Native Runtime`, good for server side apps
- `Electron Chromium`, good for Desktop Native apps
- `Capacitor`, good for Mobile apps (planned, not built yet)
- `Python Runtime`, good for MLOps workflows (planned, not built yet)
Currently, Jan works across:
- Mac Intel & Silicon
- Windows
- Ubuntu
- Nvidia GPUs
Read more:
- [Code Entrypoint](https://github.com/janhq/jan/tree/main/core)
- [Dependency Inversion](https://en.wikipedia.org/wiki/Dependency_inversion_principle)
### Local First
Jan's data persistence happens on the user's local filesystem.
We implemented abstractions on top of `fs` and other core modules in an opinionated way, s.t. user data is saved in a folder-based framework that lets users easily package, export, and manage their data.
Read more:
- [Folder-based fs wrapper](https://github.com/janhq/jan/blob/main/core/src/fs.ts)
- [Piping Node modules across infrastructures](https://github.com/janhq/jan/tree/main/core/src/node)
### AI Native
All software applications can be natively supercharged with an embedded AI server and AI abstractions.
Including:
- OpenAI Compatible AI [types](https://github.com/janhq/jan/tree/main/core/src/types) and [core extensions](https://github.com/janhq/jan/tree/main/core/src/extensions) to support common functionality like making an inference call.
- A lightweight, embedded C++ [inference engine](https://github.com/janhq/jan/tree/main/extensions/inference-nitro-extension) that's immediately callable from code.
- [Code Entrypoint](https://github.com/janhq/jan/tree/main/core/src/api)
## Fun Project Ideas
Beyond the current Jan client and UX, the Core SDK can be used to build many other AI-powered and privacy preserving applications.
- `Game engine`: For AI enabled character games, procedural generation games
- `Health app`: For a personal healthcare app that improves habits
- Got ideas? Make a PR into this docs page!
If you are interested to tackle these issues, or have suggestions for integrations and other OSS tools we can use, please hit us up in [Discord](https://discord.gg/5rQ2zTv3be).

View File

@ -32,7 +32,7 @@ Welcome to Jan! Were really excited to bring you onboard.
- We operate on the basis of trust. - We operate on the basis of trust.
- We expect you to be available and communicative during scheduled meetings or work hours. - We expect you to be available and communicative during scheduled meetings or work hours.
- Turning on video during meetings is encouraged. - Turning on video during meetings is encouraged.
- Casual dress during meetings is acceptable; however, use discretion (No naked top, pajamas, etc.) - Casual dress during meetings is acceptable; however, use discretion (No nudity, pajamas, etc.)
- While its natural for people to disagree at times, disagreement is no excuse for poor behavior and poor manners. We cannot allow that frustration to turn into a personal attack. - While its natural for people to disagree at times, disagreement is no excuse for poor behavior and poor manners. We cannot allow that frustration to turn into a personal attack.
- Respect other people's cultures. Especially since we are working in a diverse working culture. - Respect other people's cultures. Especially since we are working in a diverse working culture.
- Sexual harassment is a specific type of prohibited conduct. Sexual harassment is any unwelcome conduct of a sexual nature that might reasonably be expected or be perceived to cause offense or humiliation. Sexual harassment may involve any conduct of a verbal, nonverbal, or physical nature, including written and electronic communications, and may occur between persons of the same or different genders. - Sexual harassment is a specific type of prohibited conduct. Sexual harassment is any unwelcome conduct of a sexual nature that might reasonably be expected or be perceived to cause offense or humiliation. Sexual harassment may involve any conduct of a verbal, nonverbal, or physical nature, including written and electronic communications, and may occur between persons of the same or different genders.

View File

@ -68,6 +68,12 @@ function createMainWindow() {
if (process.platform !== 'darwin') app.quit() if (process.platform !== 'darwin') app.quit()
}) })
/* Open external links in the default browser */
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
require('electron').shell.openExternal(url)
return { action: 'deny' }
})
/* Enable dev tools for development */ /* Enable dev tools for development */
if (!app.isPackaged) mainWindow.webContents.openDevTools() if (!app.isPackaged) mainWindow.webContents.openDevTools()
} }

View File

@ -17,7 +17,7 @@
}, },
"dependencies": { "dependencies": {
"@janhq/core": "file:../../core", "@janhq/core": "file:../../core",
"os-utils": "^0.0.14", "node-os-utils": "^1.3.7",
"ts-loader": "^9.5.0" "ts-loader": "^9.5.0"
}, },
"files": [ "files": [
@ -26,6 +26,6 @@
"README.md" "README.md"
], ],
"bundleDependencies": [ "bundleDependencies": [
"os-utils" "node-os-utils"
] ]
} }

View File

@ -1,12 +1,12 @@
const os = require("os"); const os = require("os");
const osUtils = require("os-utils"); const nodeOsUtils = require("node-os-utils");
const getResourcesInfo = () => const getResourcesInfo = () =>
new Promise((resolve) => { new Promise((resolve) => {
const totalMemory = os.totalmem(); nodeOsUtils.mem.used()
const freeMemory = os.freemem(); .then(ramUsedInfo => {
const usedMemory = totalMemory - freeMemory; const totalMemory = ramUsedInfo.totalMemMb * 1024 * 1024;
const usedMemory = ramUsedInfo.usedMemMb * 1024 * 1024;
const response = { const response = {
mem: { mem: {
totalMemory, totalMemory,
@ -14,12 +14,12 @@ const getResourcesInfo = () =>
}, },
}; };
resolve(response); resolve(response);
})
}); });
const getCurrentLoad = () => const getCurrentLoad = () =>
new Promise((resolve) => { new Promise((resolve) => {
osUtils.cpuUsage(function(v){ nodeOsUtils.cpu.usage().then(cpuPercentage =>{
const cpuPercentage = v * 100;
const response = { const response = {
cpu: { cpu: {
usage: cpuPercentage, usage: cpuPercentage,

View File

@ -1,9 +1,8 @@
import fastify from "fastify"; import fastify from "fastify";
import dotenv from "dotenv"; import dotenv from "dotenv";
import { v1Router } from "@janhq/core/node"; import { log, v1Router } from "@janhq/core/node";
import path from "path"; import path from "path";
import fs from "fs";
import util from "util";
import os from "os"; import os from "os";
dotenv.config(); dotenv.config();
@ -14,18 +13,6 @@ const serverLogPath = path.join(os.homedir(), "jan", "server.log");
let server: any | undefined = undefined; let server: any | undefined = undefined;
var log_file = fs.createWriteStream(serverLogPath, {
flags: "a",
});
var log_stdout = process.stdout;
var log_stderr = process.stderr;
const logServer = function (d: any) {
log_file.write(util.format(d) + "\n");
log_stdout.write(util.format(d) + "\n");
log_stderr.write(util.format(d) + "\n");
};
export const startServer = async (schemaPath?: string, baseDir?: string) => { export const startServer = async (schemaPath?: string, baseDir?: string) => {
try { try {
server = fastify({ server = fastify({
@ -75,12 +62,10 @@ export const startServer = async (schemaPath?: string, baseDir?: string) => {
host: JAN_API_HOST, host: JAN_API_HOST,
}) })
.then(() => { .then(() => {
logServer( log(`JAN API listening at: http://${JAN_API_HOST}:${JAN_API_PORT}`);
`JAN API listening at: http://${JAN_API_HOST}:${JAN_API_PORT}`
);
}); });
} catch (e) { } catch (e) {
logServer(e); log(e);
} }
}; };
@ -88,6 +73,6 @@ export const stopServer = async () => {
try { try {
await server.close(); await server.close();
} catch (e) { } catch (e) {
logServer(e); log(e);
} }
}; };

View File

@ -11,6 +11,8 @@ import {
SettingsIcon, SettingsIcon,
MonitorIcon, MonitorIcon,
LayoutGridIcon, LayoutGridIcon,
Twitter,
Github,
} from 'lucide-react' } from 'lucide-react'
import { twMerge } from 'tailwind-merge' import { twMerge } from 'tailwind-merge'
@ -52,6 +54,23 @@ export default function RibbonNav() {
}, },
] ]
const linksMenu = [
{
name: 'Twitter',
icon: (
<Twitter size={20} className="flex-shrink-0 text-muted-foreground" />
),
link: 'https://twitter.com/janhq_',
},
{
name: 'Github',
icon: (
<Github size={20} className="flex-shrink-0 text-muted-foreground" />
),
link: 'https://github.com/janhq/jan',
},
]
const secondaryMenus = [ const secondaryMenus = [
{ {
name: 'System Monitor', name: 'System Monitor',
@ -118,6 +137,32 @@ export default function RibbonNav() {
</div> </div>
<div> <div>
<>
{linksMenu
.filter((link) => !!link)
.map((link, i) => {
return (
<div className="relative flex p-2" key={i}>
<Tooltip>
<TooltipTrigger>
<a
href={link.link}
target="_blank"
rel="noopener noreferrer"
className="relative flex w-full flex-shrink-0 cursor-pointer items-center justify-center"
>
{link.icon}
</a>
</TooltipTrigger>
<TooltipContent side="right" sideOffset={10}>
<span>{link.name}</span>
<TooltipArrow />
</TooltipContent>
</Tooltip>
</div>
)
})}
</>
{secondaryMenus {secondaryMenus
.filter((secondary) => !!secondary) .filter((secondary) => !!secondary)
.map((secondary, i) => { .map((secondary, i) => {

View File

@ -46,12 +46,12 @@ export default function useGetSystemResources() {
useEffect(() => { useEffect(() => {
getSystemResources() getSystemResources()
// Fetch interval - every 2s // Fetch interval - every 0.5s
// TODO: Will we really need this? // TODO: Will we really need this?
// There is a possibility that this will be removed and replaced by the process event hook? // There is a possibility that this will be removed and replaced by the process event hook?
const intervalId = setInterval(() => { const intervalId = setInterval(() => {
getSystemResources() getSystemResources()
}, 2000) }, 500)
// clean up interval // clean up interval
return () => clearInterval(intervalId) return () => clearInterval(intervalId)