diff --git a/.github/ISSUE_TEMPLATE/3-epic.md b/.github/ISSUE_TEMPLATE/3-epic.md
index afffc6b5c..3e05d8dd6 100644
--- a/.github/ISSUE_TEMPLATE/3-epic.md
+++ b/.github/ISSUE_TEMPLATE/3-epic.md
@@ -1,12 +1,27 @@
---
name: 🌟 Epic
-about: Major building block that advances Jan's goals
+about: User stories and specs
title: 'epic: '
type: Epic
---
-## Goal
+## User Stories
-## Tasklist
+- As a [user type], I can [do something] so that [outcome]
-## Out of scope
+## Not in scope
+
+-
+
+## User Flows & Designs
+
+- Key user flows
+- Figma link
+- Edge cases
+- Error states
+
+## Engineering Decisions
+
+- **Technical Approach:** Brief outline of the solution.
+- **Key Trade-offs:** What’s been considered/rejected and why.
+- **Dependencies:** APIs, services, libraries, teams.
diff --git a/.github/ISSUE_TEMPLATE/4-goal.md b/.github/ISSUE_TEMPLATE/4-goal.md
index 28b32382a..8d649c281 100644
--- a/.github/ISSUE_TEMPLATE/4-goal.md
+++ b/.github/ISSUE_TEMPLATE/4-goal.md
@@ -1,13 +1,38 @@
---
name: 🎯 Goal
-about: External communication of Jan's roadmap and objectives
+about: Roadmap goals for our users
title: 'goal: '
type: Goal
---
## Goal
-## Tasklist
+> Why are we doing this? 1 liner value proposition
-## Out of scope
+_e.g. Make onboarding to Jan 3x easier_
+## Success Criteria
+
+> When do we consider this done? Limit to 3.
+
+1. _e.g. Redesign onboarding flow to remove redundant steps._
+2. _e.g. Add a “getting started” guide_
+3. _e.g. Make local model setup more “normie” friendly_
+
+## Non Goals
+
+> What is out of scope?
+
+- _e.g. Take advanced users through customizing settings_
+
+## User research (if any)
+
+> Links to user messages and interviews
+
+## Design inspo
+
+> Links
+
+## Open questions
+
+> What are we not sure about?
diff --git a/.github/workflows/jan-docs.yml b/.github/workflows/jan-docs.yml
index f64f93f66..3e92903c5 100644
--- a/.github/workflows/jan-docs.yml
+++ b/.github/workflows/jan-docs.yml
@@ -76,7 +76,7 @@ jobs:
Preview URL: ${{ 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')
+ if: (github.event_name == 'push' && github.ref == 'refs/heads/dev') || (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/dev') || (github.event_name == 'workflow_dispatch' && startsWith(github.ref, 'refs/heads/release/'))
uses: cloudflare/pages-action@v1
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
diff --git a/.github/workflows/jan-linter-and-test.yml b/.github/workflows/jan-linter-and-test.yml
index e2f437837..cfcfe78ed 100644
--- a/.github/workflows/jan-linter-and-test.yml
+++ b/.github/workflows/jan-linter-and-test.yml
@@ -134,7 +134,7 @@ jobs:
test-on-windows-pr:
if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
- runs-on: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) && 'windows-latest' || 'WINDOWS-11' }}
+ runs-on: 'windows-latest'
steps:
- name: Getting the repo
uses: actions/checkout@v3
diff --git a/.github/workflows/jan-tauri-build-flatpak.yaml b/.github/workflows/jan-tauri-build-flatpak.yaml
new file mode 100644
index 000000000..2eded766a
--- /dev/null
+++ b/.github/workflows/jan-tauri-build-flatpak.yaml
@@ -0,0 +1,20 @@
+name: Tauri Builder Flatpak
+
+on:
+ workflow_dispatch:
+ inputs:
+ version:
+ description: 'Version to build. For example: 0.6.8'
+ required: false
+
+jobs:
+
+ build-linux-x64:
+ uses: ./.github/workflows/template-tauri-build-linux-x64-flatpak.yml
+ secrets: inherit
+ with:
+ ref: ${{ github.ref }}
+ public_provider: none
+ channel: stable
+ new_version: ${{ inputs.version }}
+ disable_updater: true
\ No newline at end of file
diff --git a/.github/workflows/jan-tauri-build-nightly.yaml b/.github/workflows/jan-tauri-build-nightly.yaml
index 106174eff..65a035c38 100644
--- a/.github/workflows/jan-tauri-build-nightly.yaml
+++ b/.github/workflows/jan-tauri-build-nightly.yaml
@@ -12,10 +12,31 @@ on:
- none
- aws-s3
default: none
+ disable_updater:
+ type: boolean
+ description: 'If true, builds both .deb and .appimage but disables auto-updater'
+ default: false
pull_request:
branches:
- release/**
- dev
+ paths:
+ - '.github/workflows/jan-tauri-build-nightly.yaml'
+ - '.github/workflows/template-get-update-version.yml'
+ - '.github/workflows/template-tauri-build-macos.yml'
+ - '.github/workflows/template-tauri-build-windows-x64.yml'
+ - '.github/workflows/template-tauri-build-linux-x64.yml'
+ - '.github/workflows/template-noti-discord-and-update-url-readme.yml'
+ - 'src-tauri/**'
+ - 'core/**'
+ - 'web-app/**'
+ - 'extensions/**'
+ - 'scripts/**'
+ - 'pre-install/**'
+ - 'Makefile'
+ - 'package.json'
+ - 'mise.toml'
+
jobs:
set-public-provider:
@@ -85,6 +106,7 @@ jobs:
new_version: ${{ needs.get-update-version.outputs.new_version }}
channel: nightly
cortex_api_port: '39261'
+ disable_updater: ${{ github.event.inputs.disable_updater == 'true' }}
sync-temp-to-latest:
needs:
diff --git a/.github/workflows/jan-tauri-build.yaml b/.github/workflows/jan-tauri-build.yaml
index 1dc22f2e4..95838e982 100644
--- a/.github/workflows/jan-tauri-build.yaml
+++ b/.github/workflows/jan-tauri-build.yaml
@@ -32,6 +32,7 @@ jobs:
name: "${{ env.VERSION }}"
draft: true
prerelease: false
+ generate_release_notes: true
build-macos:
uses: ./.github/workflows/template-tauri-build-macos.yml
@@ -118,28 +119,4 @@ jobs:
upload_url: ${{ needs.create-draft-release.outputs.upload_url }}
asset_path: ./latest.json
asset_name: latest.json
- asset_content_type: text/json
-
- update_release_draft:
- needs: [build-macos, build-windows-x64, build-linux-x64]
- permissions:
- # write permission is required to create a github release
- contents: write
- # write permission is required for autolabeler
- # otherwise, read permission is required at least
- pull-requests: write
- runs-on: ubuntu-latest
- steps:
- # (Optional) GitHub Enterprise requires GHE_HOST variable set
- #- name: Set GHE_HOST
- # run: |
- # echo "GHE_HOST=${GITHUB_SERVER_URL##https:\/\/}" >> $GITHUB_ENV
-
- # Drafts your next Release notes as Pull Requests are merged into "master"
- - uses: release-drafter/release-drafter@v5
- # (Optional) specify config name to use, relative to .github/. Default: release-drafter.yml
- # with:
- # config-name: my-config.yml
- # disable-autolabeler: true
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
+ asset_content_type: text/json
\ No newline at end of file
diff --git a/.github/workflows/template-tauri-build-linux-x64-flatpak.yml b/.github/workflows/template-tauri-build-linux-x64-flatpak.yml
new file mode 100644
index 000000000..2807a74ae
--- /dev/null
+++ b/.github/workflows/template-tauri-build-linux-x64-flatpak.yml
@@ -0,0 +1,164 @@
+name: tauri-build-linux-x64-flatpak
+on:
+ workflow_call:
+ inputs:
+ ref:
+ required: true
+ type: string
+ default: 'refs/heads/main'
+ public_provider:
+ required: true
+ type: string
+ default: none
+ description: 'none: build only, github: build and publish to github, aws s3: build and publish to aws s3'
+ new_version:
+ required: true
+ type: string
+ default: ''
+ cortex_api_port:
+ required: false
+ type: string
+ default: ''
+ upload_url:
+ required: false
+ type: string
+ default: ''
+ channel:
+ required: true
+ type: string
+ default: 'nightly'
+ description: 'The channel to use for this job'
+ disable_updater:
+ required: false
+ type: boolean
+ default: false
+ description: 'If true, builds both .deb and .appimage but disables auto-updater'
+ secrets:
+ DELTA_AWS_S3_BUCKET_NAME:
+ required: false
+ DELTA_AWS_ACCESS_KEY_ID:
+ required: false
+ DELTA_AWS_SECRET_ACCESS_KEY:
+ required: false
+ TAURI_SIGNING_PRIVATE_KEY:
+ required: false
+ TAURI_SIGNING_PRIVATE_KEY_PASSWORD:
+ required: false
+jobs:
+ build-linux-x64:
+ runs-on: ubuntu-22.04
+ permissions:
+ contents: write
+ steps:
+ - name: Getting the repo
+ uses: actions/checkout@v3
+ with:
+ ref: ${{ inputs.ref }}
+
+ - name: Free Disk Space Before Build
+ run: |
+ echo "Disk space before cleanup:"
+ df -h
+ sudo rm -rf /usr/local/.ghcup
+ sudo rm -rf /opt/hostedtoolcache/CodeQL
+ sudo rm -rf /usr/local/lib/android/sdk/ndk
+ sudo rm -rf /usr/share/dotnet
+ sudo rm -rf /opt/ghc
+ sudo rm -rf /usr/local/share/boost
+ sudo apt-get clean
+ echo "Disk space after cleanup:"
+ df -h
+
+ - name: Installing node
+ uses: actions/setup-node@v1
+ with:
+ node-version: 20
+
+ - name: Install jq
+ uses: dcarbone/install-jq-action@v2.0.1
+
+ - name: Install ctoml
+ run: |
+ cargo install ctoml
+
+ - name: Install Tauri dependencies
+ run: |
+ sudo apt update
+ sudo apt install -y libglib2.0-dev libatk1.0-dev libpango1.0-dev libgtk-3-dev libsoup-3.0-dev libwebkit2gtk-4.1-dev librsvg2-dev libfuse2
+
+ - name: Update app version base public_provider
+ run: |
+ echo "Version: ${{ inputs.new_version }}"
+ # Update tauri.conf.json
+ jq --arg version "${{ inputs.new_version }}" '.version = $version | .bundle.createUpdaterArtifacts = true' ./src-tauri/tauri.conf.json > /tmp/tauri.conf.json
+ mv /tmp/tauri.conf.json ./src-tauri/tauri.conf.json
+ if [ "${{ inputs.channel }}" != "stable" ]; then
+ jq '.bundle.linux.deb.files = {"usr/bin/bun": "resources/bin/bun",
+ "usr/lib/Jan-${{ inputs.channel }}/resources/lib/libvulkan.so": "resources/lib/libvulkan.so"}' ./src-tauri/tauri.linux.conf.json > /tmp/tauri.linux.conf.json
+ mv /tmp/tauri.linux.conf.json ./src-tauri/tauri.linux.conf.json
+ fi
+ jq --arg version "${{ inputs.new_version }}" '.version = $version' web-app/package.json > /tmp/package.json
+ mv /tmp/package.json web-app/package.json
+
+ # Temporarily enable devtool on prod build
+ ctoml ./src-tauri/Cargo.toml dependencies.tauri.features[] "devtools"
+ cat ./src-tauri/Cargo.toml
+
+ ctoml ./src-tauri/Cargo.toml package.version "${{ inputs.new_version }}"
+ cat ./src-tauri/Cargo.toml
+
+ # Change app name for beta and nightly builds
+ if [ "${{ inputs.channel }}" != "stable" ]; then
+ jq '.plugins.updater.endpoints = ["https://delta.jan.ai/${{ inputs.channel }}/latest.json"]' ./src-tauri/tauri.conf.json > /tmp/tauri.conf.json
+ mv /tmp/tauri.conf.json ./src-tauri/tauri.conf.json
+
+ chmod +x .github/scripts/rename-tauri-app.sh
+ .github/scripts/rename-tauri-app.sh ./src-tauri/tauri.conf.json ${{ inputs.channel }}
+
+ cat ./src-tauri/tauri.conf.json
+
+ # Update Cargo.toml
+ ctoml ./src-tauri/Cargo.toml package.name "Jan-${{ inputs.channel }}"
+ ctoml ./src-tauri/Cargo.toml dependencies.tauri.features[] "devtools"
+ echo "------------------"
+ cat ./src-tauri/Cargo.toml
+
+ chmod +x .github/scripts/rename-workspace.sh
+ .github/scripts/rename-workspace.sh ./package.json ${{ inputs.channel }}
+ cat ./package.json
+ fi
+ - name: Build app
+ run: |
+ make build
+
+ APP_IMAGE=./src-tauri/target/release/bundle/appimage/$(ls ./src-tauri/target/release/bundle/appimage/ | grep AppImage | head -1)
+ yarn tauri signer sign \
+ --private-key "$TAURI_SIGNING_PRIVATE_KEY" \
+ --password "$TAURI_SIGNING_PRIVATE_KEY_PASSWORD" \
+ "$APP_IMAGE"
+
+ env:
+ RELEASE_CHANNEL: '${{ inputs.channel }}'
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ POSTHOG_KEY: ${{ secrets.POSTHOG_KEY }}
+ POSTHOG_HOST: ${{ secrets.POSTHOG_HOST }}
+ TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
+ TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
+ AUTO_UPDATER_DISABLED: ${{ inputs.disable_updater && 'true' || 'false' }}
+ # Publish app
+
+ ## Artifacts, for dev and test
+ - name: Upload Artifact
+ if: inputs.public_provider != 'github'
+ uses: actions/upload-artifact@v4
+ with:
+ name: jan-linux-amd64-flatpak-${{ inputs.new_version }}-deb
+ path: ./src-tauri/target/release/bundle/deb/*.deb
+
+ - name: Upload Artifact
+ if: inputs.public_provider != 'github'
+ uses: actions/upload-artifact@v4
+ with:
+ name: jan-linux-amd64-flatpak-${{ inputs.new_version }}-AppImage
+ path: ./src-tauri/target/release/bundle/appimage/*.AppImage
+
diff --git a/.github/workflows/template-tauri-build-linux-x64.yml b/.github/workflows/template-tauri-build-linux-x64.yml
index 20663ea69..ef9054be1 100644
--- a/.github/workflows/template-tauri-build-linux-x64.yml
+++ b/.github/workflows/template-tauri-build-linux-x64.yml
@@ -28,6 +28,11 @@ on:
type: string
default: 'nightly'
description: 'The channel to use for this job'
+ disable_updater:
+ required: false
+ type: boolean
+ default: false
+ description: 'If true, builds both .deb and .appimage but disables auto-updater'
secrets:
DELTA_AWS_S3_BUCKET_NAME:
required: false
@@ -156,7 +161,7 @@ jobs:
POSTHOG_HOST: ${{ secrets.POSTHOG_HOST }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
-
+ AUTO_UPDATER_DISABLED: ${{ inputs.disable_updater && 'true' || 'false' }}
# Publish app
## Artifacts, for dev and test
diff --git a/.gitignore b/.gitignore
index a20f96c30..93e43d4d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,46 +1,22 @@
-.idea
.env
-.idea
-
-# Jan inference
error.log
node_modules
*.tgz
-!charts/server/charts/*.tgz
dist
build
.DS_Store
-electron/renderer
-electron/models
-electron/docs
-electron/engines
-electron/themes
-electron/playwright-report
-server/pre-install
package-lock.json
coverage
*.log
core/lib/**
-
-# Turborepo
-.turbo
-electron/test-data
-electron/test-results
-core/test_results.html
-coverage
.yarn
.yarnrc
-test_results.html
*.tsbuildinfo
-electron/shared/**
+test_results.html
# docs
docs/yarn.lock
-electron/.version.bak
-src-tauri/binaries/engines/cortex.llamacpp
-src-tauri/resources/themes
src-tauri/resources/lib
-src-tauri/Cargo.lock
src-tauri/icons
!src-tauri/icons/icon.png
src-tauri/gen/apple
@@ -75,5 +51,9 @@ docs/.next/
**/yarn-error.log*
**/pnpm-debug.log*
-# Combined output for local testing
-combined-output/
+## cargo
+target
+Cargo.lock
+
+## test
+test-data
diff --git a/Makefile b/Makefile
index 023f2c877..4bd823437 100644
--- a/Makefile
+++ b/Makefile
@@ -26,6 +26,7 @@ else ifeq ($(shell uname -s),Linux)
chmod +x src-tauri/build-utils/*
endif
yarn install
+ yarn build:tauri:plugin:api
yarn build:core
yarn build:extensions
@@ -43,6 +44,9 @@ test: lint
yarn download:bin
yarn download:lib
yarn test
+ yarn copy:assets:tauri
+ yarn build:icon
+ cargo test --manifest-path src-tauri/Cargo.toml --no-default-features --features test-tauri -- --test-threads=1
# Builds and publishes the app
build-and-publish: install-and-build
diff --git a/README.md b/README.md
index 41a41af46..b90cc8907 100644
--- a/README.md
+++ b/README.md
@@ -120,6 +120,7 @@ mise dev # runs the full development setup
```bash
yarn install
+yarn build:tauri:plugin:api
yarn build:core
yarn build:extensions
yarn dev
diff --git a/ai.menlo.jan.desktop b/ai.menlo.jan.desktop
deleted file mode 100644
index 779bffb27..000000000
--- a/ai.menlo.jan.desktop
+++ /dev/null
@@ -1,9 +0,0 @@
-[Desktop Entry]
-Name=Jan
-Comment=Local AI Assistant that runs 100% offline
-Exec=run.sh
-Icon=ai.menlo.jan
-Type=Application
-Categories=Development;
-Keywords=AI;Assistant;LLM;ChatGPT;Local;Offline;
-StartupNotify=true
\ No newline at end of file
diff --git a/ai.menlo.jan.metainfo.xml b/ai.menlo.jan.metainfo.xml
deleted file mode 100644
index ba17914e9..000000000
--- a/ai.menlo.jan.metainfo.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
- Jan is a ChatGPT-alternative that runs 100% offline on your device. Our goal is to make it easy for anyone to download and run LLMs and use AI with full control and privacy.
- Features: Latest stable release of Jan AI
-
-
+ Jan is a ChatGPT-alternative that runs 100% offline on your device. Our goal is to make it easy for anyone to download and run LLMs and use AI with full control and privacy. +
+Features:
+Latest stable release of Jan AI
+| Identifier | +Description | +
|---|---|
| + +`hardware:allow-get-system-info` + + | ++ +Enables the get_system_info command without any pre-configured scope. + + | +
| + +`hardware:deny-get-system-info` + + | ++ +Denies the get_system_info command without any pre-configured scope. + + | +
| + +`hardware:allow-get-system-usage` + + | ++ +Enables the get_system_usage command without any pre-configured scope. + + | +
| + +`hardware:deny-get-system-usage` + + | ++ +Denies the get_system_usage command without any pre-configured scope. + + | +
| Identifier | +Description | +
|---|---|
| + +`llamacpp:allow-cleanup-llama-processes` + + | ++ +Enables the cleanup_llama_processes command without any pre-configured scope. + + | +
| + +`llamacpp:deny-cleanup-llama-processes` + + | ++ +Denies the cleanup_llama_processes command without any pre-configured scope. + + | +
| + +`llamacpp:allow-find-session-by-model` + + | ++ +Enables the find_session_by_model command without any pre-configured scope. + + | +
| + +`llamacpp:deny-find-session-by-model` + + | ++ +Denies the find_session_by_model command without any pre-configured scope. + + | +
| + +`llamacpp:allow-generate-api-key` + + | ++ +Enables the generate_api_key command without any pre-configured scope. + + | +
| + +`llamacpp:deny-generate-api-key` + + | ++ +Denies the generate_api_key command without any pre-configured scope. + + | +
| + +`llamacpp:allow-get-all-sessions` + + | ++ +Enables the get_all_sessions command without any pre-configured scope. + + | +
| + +`llamacpp:deny-get-all-sessions` + + | ++ +Denies the get_all_sessions command without any pre-configured scope. + + | +
| + +`llamacpp:allow-get-devices` + + | ++ +Enables the get_devices command without any pre-configured scope. + + | +
| + +`llamacpp:deny-get-devices` + + | ++ +Denies the get_devices command without any pre-configured scope. + + | +
| + +`llamacpp:allow-get-loaded-models` + + | ++ +Enables the get_loaded_models command without any pre-configured scope. + + | +
| + +`llamacpp:deny-get-loaded-models` + + | ++ +Denies the get_loaded_models command without any pre-configured scope. + + | +
| + +`llamacpp:allow-get-random-port` + + | ++ +Enables the get_random_port command without any pre-configured scope. + + | +
| + +`llamacpp:deny-get-random-port` + + | ++ +Denies the get_random_port command without any pre-configured scope. + + | +
| + +`llamacpp:allow-get-session-by-model` + + | ++ +Enables the get_session_by_model command without any pre-configured scope. + + | +
| + +`llamacpp:deny-get-session-by-model` + + | ++ +Denies the get_session_by_model command without any pre-configured scope. + + | +
| + +`llamacpp:allow-is-process-running` + + | ++ +Enables the is_process_running command without any pre-configured scope. + + | +
| + +`llamacpp:deny-is-process-running` + + | ++ +Denies the is_process_running command without any pre-configured scope. + + | +
| + +`llamacpp:allow-load-llama-model` + + | ++ +Enables the load_llama_model command without any pre-configured scope. + + | +
| + +`llamacpp:deny-load-llama-model` + + | ++ +Denies the load_llama_model command without any pre-configured scope. + + | +
| + +`llamacpp:allow-read-gguf-metadata` + + | ++ +Enables the read_gguf_metadata command without any pre-configured scope. + + | +
| + +`llamacpp:deny-read-gguf-metadata` + + | ++ +Denies the read_gguf_metadata command without any pre-configured scope. + + | +
| + +`llamacpp:allow-unload-llama-model` + + | ++ +Enables the unload_llama_model command without any pre-configured scope. + + | +
| + +`llamacpp:deny-unload-llama-model` + + | ++ +Denies the unload_llama_model command without any pre-configured scope. + + | +