Merge branch 'dev' into feat/old-mac-support
98
.github/workflows/jan-astro-docs.yml
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
name: Jan Astro Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
paths:
|
||||
- 'website/**'
|
||||
- '.github/workflows/jan-astro-docs.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'website/**'
|
||||
- '.github/workflows/jan-astro-docs.yml'
|
||||
# Review gh actions docs if you want to further define triggers, paths, etc
|
||||
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy to CloudFlare Pages
|
||||
env:
|
||||
CLOUDFLARE_PROJECT_NAME: astro-docs
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
deployments: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
|
||||
- name: Install jq
|
||||
uses: dcarbone/install-jq-action@v2.0.1
|
||||
|
||||
- name: Fill env vars
|
||||
continue-on-error: true
|
||||
working-directory: website
|
||||
run: |
|
||||
env_example_file=".env.example"
|
||||
touch .env
|
||||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||||
if [[ "$line" == *"="* ]]; then
|
||||
var_name=$(echo $line | cut -d '=' -f 1)
|
||||
echo $var_name
|
||||
var_value="$(jq -r --arg key "$var_name" '.[$key]' <<< "$SECRETS")"
|
||||
echo "$var_name=$var_value" >> .env
|
||||
fi
|
||||
done < "$env_example_file"
|
||||
env:
|
||||
SECRETS: '${{ toJson(secrets) }}'
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: website
|
||||
run: bun install
|
||||
- name: Build website
|
||||
working-directory: website
|
||||
run: bun run build
|
||||
|
||||
- name: copy redirects and headers
|
||||
continue-on-error: true
|
||||
working-directory: website
|
||||
run: |
|
||||
cp _redirects dist/_redirects
|
||||
cp _headers dist/_headers
|
||||
|
||||
- name: Publish to Cloudflare Pages PR Preview and Staging
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: cloudflare/pages-action@v1
|
||||
with:
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
projectName: ${{ env.CLOUDFLARE_PROJECT_NAME }}
|
||||
directory: ./website/dist
|
||||
# Optional: Enable this if you want to have GitHub Deployments triggered
|
||||
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
id: deployCloudflarePages
|
||||
|
||||
- uses: mshick/add-pr-comment@v2
|
||||
if: github.event_name == 'pull_request'
|
||||
with:
|
||||
message: |
|
||||
Preview URL Astro Docs: ${{ steps.deployCloudflarePages.outputs.url }}
|
||||
|
||||
- name: Publish to Cloudflare Pages Production
|
||||
if: (github.event_name == 'push' && github.ref == 'refs/heads/dev') || (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/dev')
|
||||
uses: cloudflare/pages-action@v1
|
||||
with:
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
projectName: ${{ env.CLOUDFLARE_PROJECT_NAME }}
|
||||
directory: ./website/dist
|
||||
branch: main
|
||||
# Optional: Enable this if you want to have GitHub Deployments triggered
|
||||
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
5
.vscode/extensions.json
vendored
@ -1,5 +0,0 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"esbenp.prettier-vscode"
|
||||
]
|
||||
}
|
||||
7
.vscode/settings.json
vendored
@ -1,7 +0,0 @@
|
||||
{
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"[rust]": {
|
||||
"editor.defaultFormatter": "rust-lang.rust-analyzer"
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
{
|
||||
"-- Switcher": {
|
||||
"type": "separator",
|
||||
"title": "Switcher"
|
||||
},
|
||||
"index": {
|
||||
"display": "hidden"
|
||||
}
|
||||
}
|
||||
@ -1,87 +0,0 @@
|
||||
---
|
||||
title: Coming Soon
|
||||
description: Exciting new features and platforms are on the way. Stay tuned for Jan Web, Jan Mobile, and our API Platform.
|
||||
keywords:
|
||||
[
|
||||
Jan,
|
||||
Customizable Intelligence, LLM,
|
||||
local AI,
|
||||
privacy focus,
|
||||
free and open source,
|
||||
private and offline,
|
||||
conversational AI,
|
||||
no-subscription fee,
|
||||
large language models,
|
||||
coming soon,
|
||||
Jan Web,
|
||||
Jan Mobile,
|
||||
API Platform,
|
||||
]
|
||||
---
|
||||
|
||||
import { Callout } from 'nextra/components'
|
||||
|
||||
<div className="text-center py-12">
|
||||
<div className="mb-8">
|
||||
<h1 className="text-4xl font-bold bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent mb-4 py-2">
|
||||
🚀 Coming Soon
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-300 max-w-2xl mx-auto">
|
||||
We're working on the next stage of Jan - making our local assistant more powerful and available in more platforms.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-4xl mx-auto mb-12">
|
||||
<div className="p-6 border border-gray-200 dark:border-gray-700 rounded-lg bg-gradient-to-br from-blue-50 to-indigo-50 dark:from-blue-900/20 dark:to-indigo-900/20">
|
||||
<div className="text-3xl mb-3">🌐</div>
|
||||
<h3 className="text-lg font-semibold mb-2">Jan Web</h3>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||||
Access Jan directly from your browser with our powerful web interface
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="p-6 border border-gray-200 dark:border-gray-700 rounded-lg bg-gradient-to-br from-green-50 to-emerald-50 dark:from-green-900/20 dark:to-emerald-900/20">
|
||||
<div className="text-3xl mb-3">📱</div>
|
||||
<h3 className="text-lg font-semibold mb-2">Jan Mobile</h3>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||||
Take Jan on the go with our native mobile applications
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="p-6 border border-gray-200 dark:border-gray-700 rounded-lg bg-gradient-to-br from-purple-50 to-pink-50 dark:from-purple-900/20 dark:to-pink-900/20">
|
||||
<div className="text-3xl mb-3">⚡</div>
|
||||
<h3 className="text-lg font-semibold mb-2">Jan Server</h3>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||||
Integrate Jan's capabilities into your applications with our API
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Callout type="info">
|
||||
**Stay Updated**: Follow our [GitHub repository](https://github.com/menloresearch/jan) and join our [Discord community](https://discord.com/invite/FTk2MvZwJH) for the latest updates on these exciting releases!
|
||||
</Callout>
|
||||
|
||||
<div className="mt-12">
|
||||
<h2 className="text-2xl font-semibold mb-6">What to Expect</h2>
|
||||
<div className="text-left max-w-2xl mx-auto space-y-4">
|
||||
<div className="flex items-start gap-3">
|
||||
<span className="text-green-500 text-xl">✓</span>
|
||||
<div>
|
||||
<strong>Seamless Experience:</strong> Unified interface across all platforms
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<span className="text-green-500 text-xl">✓</span>
|
||||
<div>
|
||||
<strong>Privacy First:</strong> Same privacy-focused approach you trust
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<span className="text-green-500 text-xl">✓</span>
|
||||
<div>
|
||||
<strong>Developer Friendly:</strong> Robust APIs and comprehensive documentation
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1247,11 +1247,6 @@ export default class llamacpp_extension extends AIEngine {
|
||||
])
|
||||
args.push('--mmproj', mmprojPath)
|
||||
}
|
||||
|
||||
if (cfg.ctx_size !== undefined) {
|
||||
args.push('-c', String(cfg.ctx_size))
|
||||
}
|
||||
|
||||
// Add remaining options from the interface
|
||||
if (cfg.chat_template) args.push('--chat-template', cfg.chat_template)
|
||||
const gpu_layers =
|
||||
@ -1263,8 +1258,9 @@ export default class llamacpp_extension extends AIEngine {
|
||||
if (cfg.batch_size > 0) args.push('--batch-size', String(cfg.batch_size))
|
||||
if (cfg.ubatch_size > 0) args.push('--ubatch-size', String(cfg.ubatch_size))
|
||||
if (cfg.device.length > 0) args.push('--device', cfg.device)
|
||||
if (cfg.split_mode.length > 0) args.push('--split-mode', cfg.split_mode)
|
||||
if (cfg.main_gpu !== undefined)
|
||||
if (cfg.split_mode.length > 0 && cfg.split_mode != 'layer')
|
||||
args.push('--split-mode', cfg.split_mode)
|
||||
if (cfg.main_gpu !== undefined && cfg.main_gpu != 0)
|
||||
args.push('--main-gpu', String(cfg.main_gpu))
|
||||
|
||||
// Boolean flags
|
||||
@ -1280,18 +1276,24 @@ export default class llamacpp_extension extends AIEngine {
|
||||
} else {
|
||||
if (cfg.ctx_size > 0) args.push('--ctx-size', String(cfg.ctx_size))
|
||||
if (cfg.n_predict > 0) args.push('--n-predict', String(cfg.n_predict))
|
||||
if (cfg.cache_type_k && cfg.cache_type_k != 'f16')
|
||||
args.push('--cache-type-k', cfg.cache_type_k)
|
||||
if (
|
||||
(cfg.flash_attn && cfg.cache_type_v != 'f16') ||
|
||||
cfg.cache_type_v != 'f32'
|
||||
cfg.flash_attn &&
|
||||
(cfg.cache_type_v != 'f16' && cfg.cache_type_v != 'f32')
|
||||
) {
|
||||
args.push('--cache-type-v', cfg.cache_type_v)
|
||||
}
|
||||
if (cfg.defrag_thold && cfg.defrag_thold != 0.1)
|
||||
args.push('--defrag-thold', String(cfg.defrag_thold))
|
||||
|
||||
if (cfg.rope_scaling && cfg.rope_scaling != 'none')
|
||||
args.push('--rope-scaling', cfg.rope_scaling)
|
||||
if (cfg.rope_scale && cfg.rope_scale != 1)
|
||||
args.push('--rope-scale', String(cfg.rope_scale))
|
||||
if (cfg.rope_freq_base && cfg.rope_freq_base != 0)
|
||||
args.push('--rope-freq-base', String(cfg.rope_freq_base))
|
||||
if (cfg.rope_freq_scale && cfg.rope_freq_scale != 1)
|
||||
args.push('--rope-freq-scale', String(cfg.rope_freq_scale))
|
||||
}
|
||||
|
||||
|
||||
@ -708,3 +708,195 @@ pub async fn is_process_running(pid: i32, state: State<'_, AppState>) -> Result<
|
||||
pub fn is_port_available(port: u16) -> bool {
|
||||
std::net::TcpListener::bind(("127.0.0.1", port)).is_ok()
|
||||
}
|
||||
|
||||
// tests
|
||||
//
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_parse_multiple_devices() {
|
||||
let output = r#"ggml_vulkan: Found 2 Vulkan devices:
|
||||
ggml_vulkan: 0 = NVIDIA GeForce RTX 3090 (NVIDIA) | uma: 0 | fp16: 1 | bf16: 0 | warp size: 32 | shared memory: 49152 | int dot: 0 | matrix cores: KHR_coopmat
|
||||
ggml_vulkan: 1 = AMD Radeon Graphics (RADV GFX1151) (radv) | uma: 1 | fp16: 1 | bf16: 0 | warp size: 64 | shared memory: 65536 | int dot: 0 | matrix cores: KHR_coopmat
|
||||
Available devices:
|
||||
Vulkan0: NVIDIA GeForce RTX 3090 (24576 MiB, 24576 MiB free)
|
||||
Vulkan1: AMD Radeon Graphics (RADV GFX1151) (87722 MiB, 87722 MiB free)
|
||||
"#;
|
||||
|
||||
let devices = parse_device_output(output).unwrap();
|
||||
|
||||
assert_eq!(devices.len(), 2);
|
||||
|
||||
// Check first device
|
||||
assert_eq!(devices[0].id, "Vulkan0");
|
||||
assert_eq!(devices[0].name, "NVIDIA GeForce RTX 3090");
|
||||
assert_eq!(devices[0].mem, 24576);
|
||||
assert_eq!(devices[0].free, 24576);
|
||||
|
||||
// Check second device
|
||||
assert_eq!(devices[1].id, "Vulkan1");
|
||||
assert_eq!(devices[1].name, "AMD Radeon Graphics (RADV GFX1151)");
|
||||
assert_eq!(devices[1].mem, 87722);
|
||||
assert_eq!(devices[1].free, 87722);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_single_device() {
|
||||
let output = r#"Available devices:
|
||||
CUDA0: NVIDIA GeForce RTX 4090 (24576 MiB, 24000 MiB free)"#;
|
||||
|
||||
let devices = parse_device_output(output).unwrap();
|
||||
|
||||
assert_eq!(devices.len(), 1);
|
||||
assert_eq!(devices[0].id, "CUDA0");
|
||||
assert_eq!(devices[0].name, "NVIDIA GeForce RTX 4090");
|
||||
assert_eq!(devices[0].mem, 24576);
|
||||
assert_eq!(devices[0].free, 24000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_with_extra_whitespace_and_empty_lines() {
|
||||
let output = r#"
|
||||
Available devices:
|
||||
|
||||
Vulkan0: NVIDIA GeForce RTX 3090 (24576 MiB, 24576 MiB free)
|
||||
|
||||
Vulkan1: AMD Radeon Graphics (RADV GFX1151) (87722 MiB, 87722 MiB free)
|
||||
|
||||
"#;
|
||||
|
||||
let devices = parse_device_output(output).unwrap();
|
||||
|
||||
assert_eq!(devices.len(), 2);
|
||||
assert_eq!(devices[0].id, "Vulkan0");
|
||||
assert_eq!(devices[1].id, "Vulkan1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_different_backends() {
|
||||
let output = r#"Available devices:
|
||||
CUDA0: NVIDIA GeForce RTX 4090 (24576 MiB, 24000 MiB free)
|
||||
Vulkan0: NVIDIA GeForce RTX 3090 (24576 MiB, 24576 MiB free)
|
||||
SYCL0: Intel(R) Arc(TM) A750 Graphics (8000 MiB, 7721 MiB free)"#;
|
||||
|
||||
let devices = parse_device_output(output).unwrap();
|
||||
|
||||
assert_eq!(devices.len(), 3);
|
||||
|
||||
assert_eq!(devices[0].id, "CUDA0");
|
||||
assert_eq!(devices[0].name, "NVIDIA GeForce RTX 4090");
|
||||
|
||||
assert_eq!(devices[1].id, "Vulkan0");
|
||||
assert_eq!(devices[1].name, "NVIDIA GeForce RTX 3090");
|
||||
|
||||
assert_eq!(devices[2].id, "SYCL0");
|
||||
assert_eq!(devices[2].name, "Intel(R) Arc(TM) A750 Graphics");
|
||||
assert_eq!(devices[2].mem, 8000);
|
||||
assert_eq!(devices[2].free, 7721);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_complex_gpu_names() {
|
||||
let output = r#"Available devices:
|
||||
Vulkan0: Intel(R) Arc(tm) A750 Graphics (DG2) (8128 MiB, 8128 MiB free)
|
||||
Vulkan1: AMD Radeon RX 7900 XTX (Navi 31) [RDNA 3] (24576 MiB, 24000 MiB free)"#;
|
||||
|
||||
let devices = parse_device_output(output).unwrap();
|
||||
|
||||
assert_eq!(devices.len(), 2);
|
||||
|
||||
assert_eq!(devices[0].id, "Vulkan0");
|
||||
assert_eq!(devices[0].name, "Intel(R) Arc(tm) A750 Graphics (DG2)");
|
||||
assert_eq!(devices[0].mem, 8128);
|
||||
assert_eq!(devices[0].free, 8128);
|
||||
|
||||
assert_eq!(devices[1].id, "Vulkan1");
|
||||
assert_eq!(devices[1].name, "AMD Radeon RX 7900 XTX (Navi 31) [RDNA 3]");
|
||||
assert_eq!(devices[1].mem, 24576);
|
||||
assert_eq!(devices[1].free, 24000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_no_devices() {
|
||||
let output = r#"Available devices:"#;
|
||||
|
||||
let devices = parse_device_output(output).unwrap();
|
||||
assert_eq!(devices.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_missing_header() {
|
||||
let output = r#"Vulkan0: NVIDIA GeForce RTX 3090 (24576 MiB, 24576 MiB free)"#;
|
||||
|
||||
let result = parse_device_output(output);
|
||||
assert!(result.is_err());
|
||||
assert!(result
|
||||
.unwrap_err()
|
||||
.to_string()
|
||||
.contains("Could not find 'Available devices:' section"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_malformed_device_line() {
|
||||
let output = r#"Available devices:
|
||||
Vulkan0: NVIDIA GeForce RTX 3090 (24576 MiB, 24576 MiB free)
|
||||
Invalid line without colon
|
||||
Vulkan1: AMD Radeon Graphics (RADV GFX1151) (87722 MiB, 87722 MiB free)"#;
|
||||
|
||||
let devices = parse_device_output(output).unwrap();
|
||||
|
||||
// Should skip the malformed line and parse the valid ones
|
||||
assert_eq!(devices.len(), 2);
|
||||
assert_eq!(devices[0].id, "Vulkan0");
|
||||
assert_eq!(devices[1].id, "Vulkan1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_device_line_individual() {
|
||||
// Test the individual line parser
|
||||
let line = "Vulkan0: NVIDIA GeForce RTX 3090 (24576 MiB, 24576 MiB free)";
|
||||
let device = parse_device_line(line).unwrap().unwrap();
|
||||
|
||||
assert_eq!(device.id, "Vulkan0");
|
||||
assert_eq!(device.name, "NVIDIA GeForce RTX 3090");
|
||||
assert_eq!(device.mem, 24576);
|
||||
assert_eq!(device.free, 24576);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_memory_pattern_detection() {
|
||||
assert!(is_memory_pattern("24576 MiB, 24576 MiB free"));
|
||||
assert!(is_memory_pattern("8000 MiB, 7721 MiB free"));
|
||||
assert!(!is_memory_pattern("just some text"));
|
||||
assert!(!is_memory_pattern("24576 MiB"));
|
||||
assert!(!is_memory_pattern("24576, 24576"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_memory_value() {
|
||||
assert_eq!(parse_memory_value("24576 MiB").unwrap(), 24576);
|
||||
assert_eq!(parse_memory_value("7721 MiB free").unwrap(), 7721);
|
||||
assert_eq!(parse_memory_value("8000").unwrap(), 8000);
|
||||
|
||||
assert!(parse_memory_value("").is_err());
|
||||
assert!(parse_memory_value("not_a_number MiB").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_find_memory_pattern() {
|
||||
let text = "NVIDIA GeForce RTX 3090 (24576 MiB, 24576 MiB free)";
|
||||
let result = find_memory_pattern(text);
|
||||
assert!(result.is_some());
|
||||
let (_start, content) = result.unwrap();
|
||||
assert_eq!(content, "24576 MiB, 24576 MiB free");
|
||||
|
||||
// Test with multiple parentheses
|
||||
let text = "Intel(R) Arc(tm) A750 Graphics (DG2) (8128 MiB, 8128 MiB free)";
|
||||
let result = find_memory_pattern(text);
|
||||
assert!(result.is_some());
|
||||
let (_start, content) = result.unwrap();
|
||||
assert_eq!(content, "8128 MiB, 8128 MiB free");
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,8 +161,14 @@ export function DownloadManagement() {
|
||||
console.debug('onFileDownloadError', state)
|
||||
removeDownload(state.modelId)
|
||||
removeLocalDownloadingModel(state.modelId)
|
||||
toast.error(t('common:toast.downloadFailed.title'), {
|
||||
id: 'download-failed',
|
||||
description: t('common:toast.downloadFailed.description', {
|
||||
item: state.modelId,
|
||||
}),
|
||||
})
|
||||
},
|
||||
[removeDownload, removeLocalDownloadingModel]
|
||||
[removeDownload, removeLocalDownloadingModel, t]
|
||||
)
|
||||
|
||||
const onFileDownloadStopped = useCallback(
|
||||
|
||||
@ -36,7 +36,10 @@ export default function OutOfContextPromiseModal() {
|
||||
|
||||
return (
|
||||
<Dialog open={isModalOpen} onOpenChange={handleDialogOpen}>
|
||||
<DialogContent>
|
||||
<DialogContent
|
||||
showCloseButton={false}
|
||||
onInteractOutside={(e) => e.preventDefault()}
|
||||
>
|
||||
<DialogHeader>
|
||||
<DialogTitle>{t('model-errors:title')}</DialogTitle>
|
||||
</DialogHeader>
|
||||
@ -57,7 +60,7 @@ export default function OutOfContextPromiseModal() {
|
||||
{t('model-errors:truncateInput')}
|
||||
</Button>
|
||||
<Button
|
||||
asChild
|
||||
autoFocus
|
||||
onClick={() => {
|
||||
handleContextLength()
|
||||
}}
|
||||
|
||||
@ -365,8 +365,7 @@ export const useChat = () => {
|
||||
if (
|
||||
typeof errorMessage === 'string' &&
|
||||
errorMessage.includes(OUT_OF_CONTEXT_SIZE) &&
|
||||
selectedModel &&
|
||||
troubleshooting
|
||||
selectedModel
|
||||
) {
|
||||
const method = await showIncreaseContextSizeModal()
|
||||
if (method === 'ctx_len') {
|
||||
|
||||
@ -257,6 +257,10 @@
|
||||
"downloadCancelled": {
|
||||
"title": "Download Cancelled",
|
||||
"description": "The download process was cancelled"
|
||||
},
|
||||
"downloadFailed": {
|
||||
"title": "Download Failed",
|
||||
"description": "{{item}} download failed"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,8 +4,7 @@ import { UIEventHandler } from 'react'
|
||||
import debounce from 'lodash.debounce'
|
||||
import cloneDeep from 'lodash.clonedeep'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { ArrowDown } from 'lucide-react'
|
||||
import { Play } from 'lucide-react'
|
||||
import { ArrowDown, Play } from 'lucide-react'
|
||||
|
||||
import HeaderPage from '@/containers/HeaderPage'
|
||||
import { useThreads } from '@/hooks/useThreads'
|
||||
@ -328,7 +327,7 @@ function ThreadDetail() {
|
||||
>
|
||||
{showScrollToBottomBtn && (
|
||||
<div
|
||||
className="bg-main-view-fg/10 px-4 border border-main-view-fg/5 flex items-center justify-center rounded-xl gap-x-2 cursor-pointer pointer-events-auto"
|
||||
className="bg-main-view-fg/10 px-2 border border-main-view-fg/5 flex items-center justify-center rounded-xl gap-x-2 cursor-pointer pointer-events-auto"
|
||||
onClick={() => {
|
||||
scrollToBottom(true)
|
||||
setIsUserScrolling(false)
|
||||
@ -340,7 +339,7 @@ function ThreadDetail() {
|
||||
)}
|
||||
{showGenerateAIResponseBtn && (
|
||||
<div
|
||||
className="bg-main-view-fg/10 px-4 border border-main-view-fg/5 flex items-center justify-center rounded-xl gap-x-2 cursor-pointer pointer-events-auto"
|
||||
className="mx-2 bg-main-view-fg/10 px-2 border border-main-view-fg/5 flex items-center justify-center rounded-xl gap-x-2 cursor-pointer pointer-events-auto"
|
||||
onClick={generateAIResponse}
|
||||
>
|
||||
<p className="text-xs">{t('common:generateAiResponse')}</p>
|
||||
|
||||
21
website/.gitignore
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# build output
|
||||
dist/
|
||||
# generated types
|
||||
.astro/
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
# logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
|
||||
# environment variables
|
||||
.env
|
||||
.env.production
|
||||
|
||||
# macOS-specific files
|
||||
.DS_Store
|
||||
28
website/README.md
Normal file
@ -0,0 +1,28 @@
|
||||
# Jan's Website
|
||||
|
||||
This website is [built with Starlight](https://starlight.astro.build)
|
||||
|
||||
|
||||
Starlight looks for `.md` or `.mdx` files in the `src/content/docs/` directory. Each file is exposed
|
||||
as a route based on its file name.
|
||||
|
||||
Images can be added to `src/assets/` and embedded in Markdown with a relative link.
|
||||
|
||||
Static assets, like favicons, can be placed in the `public/` directory.
|
||||
|
||||
If you want to add new pages, these can go in the `src/pages/` directory. Because of the topics plugin
|
||||
we are using ([starlight sidebar topics](https://starlight-sidebar-topics.netlify.app/docs/guides/excluded-pages/))
|
||||
you will need to exclude them from the sidebar by adding them to the exclude list in `astro.config.mjs`, e.g., `exclude: ['/example'],`.
|
||||
|
||||
## 🧞 Commands
|
||||
|
||||
All commands are run from the root of the project, from a terminal:
|
||||
|
||||
| Command | Action |
|
||||
| :------------------------ | :----------------------------------------------- |
|
||||
| `bun install` | Installs dependencies |
|
||||
| `bun dev` | Starts local dev server at `localhost:4321` |
|
||||
| `bun build` | Build your production site to `./dist/` |
|
||||
| `bun preview` | Preview your build locally, before deploying |
|
||||
| `bun astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||
| `bun astro -- --help` | Get help using the Astro CLI |
|
||||
175
website/astro.config.mjs
Normal file
@ -0,0 +1,175 @@
|
||||
// @ts-check
|
||||
import { defineConfig } from 'astro/config'
|
||||
import starlight from '@astrojs/starlight'
|
||||
import starlightThemeRapide from 'starlight-theme-rapide'
|
||||
import starlightSidebarTopics from 'starlight-sidebar-topics'
|
||||
import mermaid from 'astro-mermaid'
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
// Deploy to the new v2 subdomain
|
||||
site: 'https://v2.jan.ai',
|
||||
// No 'base' property is needed, as this will be deployed to the root of the subdomain.
|
||||
integrations: [
|
||||
mermaid({
|
||||
theme: 'default',
|
||||
autoTheme: true,
|
||||
}),
|
||||
starlight({
|
||||
title: '👋 Jan',
|
||||
favicon: 'jan2.png',
|
||||
plugins: [
|
||||
starlightThemeRapide(),
|
||||
starlightSidebarTopics(
|
||||
[
|
||||
{
|
||||
label: 'Jan Desktop',
|
||||
link: '/',
|
||||
icon: 'rocket',
|
||||
items: [
|
||||
{
|
||||
label: 'HOW TO',
|
||||
items: [
|
||||
{
|
||||
label: 'Install 👋 Jan',
|
||||
collapsed: false,
|
||||
autogenerate: { directory: 'jan/installation' },
|
||||
},
|
||||
{ label: 'Start Chatting', slug: 'jan/threads' },
|
||||
{
|
||||
label: 'Use Jan Models',
|
||||
collapsed: true,
|
||||
autogenerate: { directory: 'jan/jan-models' },
|
||||
},
|
||||
{ label: 'Assistants', slug: 'jan/assistants' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Cloud Providers',
|
||||
items: [
|
||||
{ label: 'Anthropic', slug: 'jan/remote-models/anthropic' },
|
||||
{ label: 'OpenAI', slug: 'jan/remote-models/openai' },
|
||||
{ label: 'Gemini', slug: 'jan/remote-models/google' },
|
||||
{
|
||||
label: 'OpenRouter',
|
||||
slug: 'jan/remote-models/openrouter',
|
||||
},
|
||||
{ label: 'Cohere', slug: 'jan/remote-models/cohere' },
|
||||
{ label: 'Mistral', slug: 'jan/remote-models/mistralai' },
|
||||
{ label: 'Groq', slug: 'jan/remote-models/groq' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'EXPLANATION',
|
||||
items: [
|
||||
{
|
||||
label: 'Local AI Engine',
|
||||
slug: 'jan/explanation/llama-cpp',
|
||||
},
|
||||
{
|
||||
label: 'Model Parameters',
|
||||
slug: 'jan/explanation/model-parameters',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'ADVANCED',
|
||||
items: [
|
||||
{ label: 'Manage Models', slug: 'jan/manage-models' },
|
||||
{ label: 'Model Context Protocol', slug: 'jan/mcp' },
|
||||
{
|
||||
label: 'MCP Examples',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
label: 'Code Sandbox (E2B)',
|
||||
slug: 'jan/mcp-examples/data-analysis/e2b',
|
||||
},
|
||||
{
|
||||
label: 'Web Search with Exa',
|
||||
slug: 'jan/mcp-examples/search/exa',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Local Server',
|
||||
items: [
|
||||
{ label: 'Introduction', link: '/local-server/' },
|
||||
{ label: 'Server Setup', slug: 'local-server/api-server' },
|
||||
{
|
||||
label: 'Jan Data Folder',
|
||||
slug: 'local-server/data-folder',
|
||||
},
|
||||
{ label: 'Server Settings', slug: 'local-server/settings' },
|
||||
{
|
||||
label: 'Llama.cpp Server',
|
||||
slug: 'local-server/llama-cpp',
|
||||
},
|
||||
{
|
||||
label: 'Integrations',
|
||||
collapsed: true,
|
||||
autogenerate: { directory: 'local-server/integrations' },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'REFERENCE',
|
||||
items: [
|
||||
{ label: 'Settings', slug: 'jan/settings' },
|
||||
{ label: 'Jan Data Folder', slug: 'jan/data-folder' },
|
||||
{ label: 'Troubleshooting', slug: 'jan/troubleshooting' },
|
||||
{ label: 'Privacy Policy', slug: 'jan/privacy' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Jan Mobile',
|
||||
link: '/mobile/',
|
||||
badge: { text: 'Coming Soon', variant: 'caution' },
|
||||
icon: 'phone',
|
||||
items: [{ label: 'Overview', slug: 'mobile' }],
|
||||
},
|
||||
{
|
||||
label: 'Jan Server',
|
||||
link: '/server/',
|
||||
badge: { text: 'Coming Soon', variant: 'caution' },
|
||||
icon: 'forward-slash',
|
||||
items: [{ label: 'Overview', slug: 'server' }],
|
||||
},
|
||||
],
|
||||
{
|
||||
exclude: [
|
||||
'/prods',
|
||||
'/api-reference',
|
||||
'/products',
|
||||
'/products/**/*',
|
||||
],
|
||||
}
|
||||
),
|
||||
],
|
||||
social: [
|
||||
{
|
||||
icon: 'github',
|
||||
label: 'GitHub',
|
||||
href: 'https://github.com/menloresearch/jan',
|
||||
},
|
||||
{
|
||||
icon: 'x.com',
|
||||
label: 'X',
|
||||
href: 'https://twitter.com/jandotai',
|
||||
},
|
||||
{
|
||||
icon: 'discord',
|
||||
label: 'Discord',
|
||||
href: 'https://discord.com/invite/FTk2MvZwJH',
|
||||
},
|
||||
],
|
||||
components: {
|
||||
Header: './src/components/CustomNav.astro',
|
||||
},
|
||||
}),
|
||||
],
|
||||
})
|
||||
1299
website/bun.lock
Normal file
27
website/package.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "website",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/starlight": "^0.35.1",
|
||||
"@lorenzo_lewis/starlight-utils": "^0.3.2",
|
||||
"astro": "^5.6.1",
|
||||
"astro-mermaid": "^1.0.4",
|
||||
"gsap": "^3.13.0",
|
||||
"mermaid": "^11.9.0",
|
||||
"phosphor-astro": "^2.1.0",
|
||||
"sharp": "^0.34.3",
|
||||
"starlight-openapi": "^0.19.1",
|
||||
"starlight-sidebar-topics": "^0.6.0",
|
||||
"starlight-theme-rapide": "^0.5.1",
|
||||
"starlight-videos": "^0.3.0"
|
||||
},
|
||||
"packageManager": "yarn@1.22.22"
|
||||
}
|
||||
1
website/public/favicon.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M81 36 64 0 47 36l-1 2-9-10a6 6 0 0 0-9 9l10 10h-2L0 64l36 17h2L28 91a6 6 0 1 0 9 9l9-10 1 2 17 36 17-36v-2l9 10a6 6 0 1 0 9-9l-9-9 2-1 36-17-36-17-2-1 9-9a6 6 0 1 0-9-9l-9 10v-2Zm-17 2-2 5c-4 8-11 15-19 19l-5 2 5 2c8 4 15 11 19 19l2 5 2-5c4-8 11-15 19-19l5-2-5-2c-8-4-15-11-19-19l-2-5Z" clip-rule="evenodd"/><path d="M118 19a6 6 0 0 0-9-9l-3 3a6 6 0 1 0 9 9l3-3Zm-96 4c-2 2-6 2-9 0l-3-3a6 6 0 1 1 9-9l3 3c3 2 3 6 0 9Zm0 82c-2-2-6-2-9 0l-3 3a6 6 0 1 0 9 9l3-3c3-2 3-6 0-9Zm96 4a6 6 0 0 1-9 9l-3-3a6 6 0 1 1 9-9l3 3Z"/><style>path{fill:#000}@media (prefers-color-scheme:dark){path{fill:#fff}}</style></svg>
|
||||
|
After Width: | Height: | Size: 696 B |
BIN
website/public/gifs/jan-nano-demo.gif
Normal file
|
After Width: | Height: | Size: 22 MiB |
BIN
website/public/jan.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
website/public/jan2.png
Normal file
|
After Width: | Height: | Size: 1.8 MiB |
1459
website/public/openapi/openapi.json
Normal file
BIN
website/public/videos/jan-nano-demo.mp4
Normal file
BIN
website/src/assets/add_assistant.png
Normal file
|
After Width: | Height: | Size: 163 KiB |
BIN
website/src/assets/anthropic.png
Normal file
|
After Width: | Height: | Size: 149 KiB |
BIN
website/src/assets/api-server-logs.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
website/src/assets/api-server-ui.png
Normal file
|
After Width: | Height: | Size: 562 KiB |
BIN
website/src/assets/api-server.png
Normal file
|
After Width: | Height: | Size: 598 KiB |
BIN
website/src/assets/api-server2.png
Normal file
|
After Width: | Height: | Size: 306 KiB |
BIN
website/src/assets/assistant-add-dialog.png
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
website/src/assets/assistant-dropdown-updated.png
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
website/src/assets/assistant-dropdown.png
Normal file
|
After Width: | Height: | Size: 450 KiB |
BIN
website/src/assets/assistant-edit-dialog.png
Normal file
|
After Width: | Height: | Size: 118 KiB |
BIN
website/src/assets/assistants-ui-overview.png
Normal file
|
After Width: | Height: | Size: 453 KiB |
BIN
website/src/assets/cohere.png
Normal file
|
After Width: | Height: | Size: 524 KiB |
BIN
website/src/assets/deepseek.png
Normal file
|
After Width: | Height: | Size: 147 KiB |
BIN
website/src/assets/e2b-key.png
Normal file
|
After Width: | Height: | Size: 266 KiB |
BIN
website/src/assets/e2b-key1.png
Normal file
|
After Width: | Height: | Size: 247 KiB |
BIN
website/src/assets/e2b-key2.png
Normal file
|
After Width: | Height: | Size: 314 KiB |
BIN
website/src/assets/e2b-key3.png
Normal file
|
After Width: | Height: | Size: 308 KiB |
BIN
website/src/assets/e2b-key4.png
Normal file
|
After Width: | Height: | Size: 500 KiB |
BIN
website/src/assets/e2b-key5.png
Normal file
|
After Width: | Height: | Size: 314 KiB |
BIN
website/src/assets/e2b-key6.png
Normal file
|
After Width: | Height: | Size: 558 KiB |
BIN
website/src/assets/e2b-key7.png
Normal file
|
After Width: | Height: | Size: 649 KiB |
BIN
website/src/assets/exa.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
website/src/assets/exa1.png
Normal file
|
After Width: | Height: | Size: 340 KiB |
BIN
website/src/assets/exa2.png
Normal file
|
After Width: | Height: | Size: 507 KiB |
BIN
website/src/assets/exa3.png
Normal file
|
After Width: | Height: | Size: 468 KiB |
BIN
website/src/assets/exa4.png
Normal file
|
After Width: | Height: | Size: 662 KiB |
BIN
website/src/assets/extensions-01.png
Normal file
|
After Width: | Height: | Size: 160 KiB |
BIN
website/src/assets/extensions-02.png
Normal file
|
After Width: | Height: | Size: 142 KiB |
BIN
website/src/assets/extensions-03.png
Normal file
|
After Width: | Height: | Size: 140 KiB |
BIN
website/src/assets/extensions-04.png
Normal file
|
After Width: | Height: | Size: 162 KiB |
BIN
website/src/assets/extensions-05.png
Normal file
|
After Width: | Height: | Size: 185 KiB |
BIN
website/src/assets/extensions-06.png
Normal file
|
After Width: | Height: | Size: 185 KiB |
BIN
website/src/assets/extensions-07.png
Normal file
|
After Width: | Height: | Size: 187 KiB |
BIN
website/src/assets/extensions-08.png
Normal file
|
After Width: | Height: | Size: 187 KiB |
BIN
website/src/assets/extensions-09.png
Normal file
|
After Width: | Height: | Size: 192 KiB |
BIN
website/src/assets/extensions-10.png
Normal file
|
After Width: | Height: | Size: 187 KiB |
BIN
website/src/assets/google.png
Normal file
|
After Width: | Height: | Size: 541 KiB |
BIN
website/src/assets/gpu_accl.png
Normal file
|
After Width: | Height: | Size: 257 KiB |
BIN
website/src/assets/groq.png
Normal file
|
After Width: | Height: | Size: 537 KiB |
BIN
website/src/assets/hardware.png
Normal file
|
After Width: | Height: | Size: 576 KiB |
BIN
website/src/assets/hf-unsloth.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
website/src/assets/hf_and_jan.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
website/src/assets/hf_token.png
Normal file
|
After Width: | Height: | Size: 487 KiB |
BIN
website/src/assets/houston.webp
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
website/src/assets/install-engines-01.png
Normal file
|
After Width: | Height: | Size: 170 KiB |
BIN
website/src/assets/install-engines-02.png
Normal file
|
After Width: | Height: | Size: 166 KiB |
BIN
website/src/assets/install-engines-03.png
Normal file
|
After Width: | Height: | Size: 183 KiB |
BIN
website/src/assets/jan-app-new.png
Normal file
|
After Width: | Height: | Size: 343 KiB |
BIN
website/src/assets/jan-app.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
website/src/assets/jan-nano-bench.png
Normal file
|
After Width: | Height: | Size: 205 KiB |
BIN
website/src/assets/jan-nano0.png
Normal file
|
After Width: | Height: | Size: 4.4 MiB |
BIN
website/src/assets/jan-nano1.png
Normal file
|
After Width: | Height: | Size: 819 KiB |
BIN
website/src/assets/jan-server.png
Normal file
|
After Width: | Height: | Size: 357 KiB |
BIN
website/src/assets/jan-vision.png
Normal file
|
After Width: | Height: | Size: 745 KiB |
BIN
website/src/assets/jan_desktop.png
Normal file
|
After Width: | Height: | Size: 209 KiB |
BIN
website/src/assets/jan_everywhere.png
Normal file
|
After Width: | Height: | Size: 619 KiB |
BIN
website/src/assets/jan_mobile.png
Normal file
|
After Width: | Height: | Size: 136 KiB |
BIN
website/src/assets/jan_mobile2.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
website/src/assets/jan_mobile3.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
website/src/assets/jan_mobile4.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
website/src/assets/jan_mobile5.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
website/src/assets/jan_mobile6.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
website/src/assets/jan_mobile7.png
Normal file
|
After Width: | Height: | Size: 501 KiB |
BIN
website/src/assets/jan_sync.png
Normal file
|
After Width: | Height: | Size: 481 KiB |
BIN
website/src/assets/jan_ui.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
website/src/assets/jan_web.png
Normal file
|
After Width: | Height: | Size: 313 KiB |
BIN
website/src/assets/llama.cpp-01-updated.png
Normal file
|
After Width: | Height: | Size: 512 KiB |
BIN
website/src/assets/llama.cpp-01.png
Normal file
|
After Width: | Height: | Size: 199 KiB |
BIN
website/src/assets/ls.png
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
website/src/assets/martian.png
Normal file
|
After Width: | Height: | Size: 144 KiB |
BIN
website/src/assets/mcp-on.png
Normal file
|
After Width: | Height: | Size: 337 KiB |
BIN
website/src/assets/mcp-server.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
website/src/assets/mcp-setup-1.png
Normal file
|
After Width: | Height: | Size: 126 KiB |
BIN
website/src/assets/mcp-setup-10.png
Normal file
|
After Width: | Height: | Size: 992 KiB |
BIN
website/src/assets/mcp-setup-2.png
Normal file
|
After Width: | Height: | Size: 439 KiB |
BIN
website/src/assets/mcp-setup-3.png
Normal file
|
After Width: | Height: | Size: 284 KiB |
BIN
website/src/assets/mcp-setup-4.png
Normal file
|
After Width: | Height: | Size: 514 KiB |