commit
f43fae2e86
2
.github/scripts/auto-sign.sh
vendored
2
.github/scripts/auto-sign.sh
vendored
@ -8,3 +8,5 @@ fi
|
|||||||
|
|
||||||
# If both variables are set, execute the following commands
|
# If both variables are set, execute the following commands
|
||||||
find "$APP_PATH" \( -type f -perm +111 -o -name "*.node" \) -exec codesign -s "$DEVELOPER_ID" --options=runtime {} \;
|
find "$APP_PATH" \( -type f -perm +111 -o -name "*.node" \) -exec codesign -s "$DEVELOPER_ID" --options=runtime {} \;
|
||||||
|
|
||||||
|
find "$APP_PATH" -type f -name "*.o" -exec codesign -s "$DEVELOPER_ID" --options=runtime {} \;
|
||||||
|
|||||||
62
.github/workflows/jan-electron-build-nightly.yml
vendored
62
.github/workflows/jan-electron-build-nightly.yml
vendored
@ -48,8 +48,17 @@ jobs:
|
|||||||
get-update-version:
|
get-update-version:
|
||||||
uses: ./.github/workflows/template-get-update-version.yml
|
uses: ./.github/workflows/template-get-update-version.yml
|
||||||
|
|
||||||
build-macos:
|
build-macos-x64:
|
||||||
uses: ./.github/workflows/template-build-macos.yml
|
uses: ./.github/workflows/template-build-macos-x64.yml
|
||||||
|
needs: [get-update-version, set-public-provider]
|
||||||
|
secrets: inherit
|
||||||
|
with:
|
||||||
|
ref: ${{ needs.set-public-provider.outputs.ref }}
|
||||||
|
public_provider: ${{ needs.set-public-provider.outputs.public_provider }}
|
||||||
|
new_version: ${{ needs.get-update-version.outputs.new_version }}
|
||||||
|
|
||||||
|
build-macos-arm64:
|
||||||
|
uses: ./.github/workflows/template-build-macos-arm64.yml
|
||||||
needs: [get-update-version, set-public-provider]
|
needs: [get-update-version, set-public-provider]
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
with:
|
with:
|
||||||
@ -76,8 +85,51 @@ jobs:
|
|||||||
public_provider: ${{ needs.set-public-provider.outputs.public_provider }}
|
public_provider: ${{ needs.set-public-provider.outputs.public_provider }}
|
||||||
new_version: ${{ needs.get-update-version.outputs.new_version }}
|
new_version: ${{ needs.get-update-version.outputs.new_version }}
|
||||||
|
|
||||||
|
combine-latest-mac-yml:
|
||||||
|
needs: [set-public-provider, build-macos-x64, build-macos-arm64]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Getting the repo
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: ${{ needs.set-public-provider.outputs.ref }}
|
||||||
|
- name: Download mac-x64 artifacts
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: latest-mac-x64
|
||||||
|
path: ./latest-mac-x64
|
||||||
|
- name: Download mac-arm artifacts
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: latest-mac-arm64
|
||||||
|
path: ./latest-mac-arm64
|
||||||
|
|
||||||
|
- name: 'Merge latest-mac.yml'
|
||||||
|
# unfortunately electron-builder doesn't understand that we have two different releases for mac-x64 and mac-arm, so we need to manually merge the latest files
|
||||||
|
# see https://github.com/electron-userland/electron-builder/issues/5592
|
||||||
|
run: |
|
||||||
|
ls -la .
|
||||||
|
ls -la ./latest-mac-x64
|
||||||
|
ls -la ./latest-mac-arm64
|
||||||
|
ls -la ./electron
|
||||||
|
cp ./electron/merge-latest-ymls.js /tmp/merge-latest-ymls.js
|
||||||
|
npm install js-yaml --prefix /tmp
|
||||||
|
node /tmp/merge-latest-ymls.js ./latest-mac-x64/latest-mac.yml ./latest-mac-arm64/latest-mac.yml ./latest-mac.yml
|
||||||
|
cat ./latest-mac.yml
|
||||||
|
|
||||||
|
- name: Upload latest-mac.yml
|
||||||
|
if: ${{ needs.set-public-provider.outputs.public_provider == 'cloudflare-r2' }}
|
||||||
|
run: |
|
||||||
|
aws s3api put-object --endpoint-url https://${{ secrets.CLOUDFLARE_ACCOUNT_ID }}.r2.cloudflarestorage.com --bucket ${{ secrets.CLOUDFLARE_R2_BUCKET_NAME }} --key "latest/latest-mac.yml" --body "./latest-mac.yml"
|
||||||
|
env:
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_DEFAULT_REGION: auto
|
||||||
|
AWS_EC2_METADATA_DISABLED: "true"
|
||||||
|
|
||||||
|
|
||||||
noti-discord-nightly-and-update-url-readme:
|
noti-discord-nightly-and-update-url-readme:
|
||||||
needs: [build-macos, build-windows-x64, build-linux-x64, get-update-version, set-public-provider]
|
needs: [build-macos-x64, build-macos-arm64, build-windows-x64, build-linux-x64, get-update-version, set-public-provider, combine-latest-mac-yml]
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
if: github.event_name == 'schedule'
|
if: github.event_name == 'schedule'
|
||||||
uses: ./.github/workflows/template-noti-discord-and-update-url-readme.yml
|
uses: ./.github/workflows/template-noti-discord-and-update-url-readme.yml
|
||||||
@ -88,7 +140,7 @@ jobs:
|
|||||||
new_version: ${{ needs.get-update-version.outputs.new_version }}
|
new_version: ${{ needs.get-update-version.outputs.new_version }}
|
||||||
|
|
||||||
noti-discord-pre-release-and-update-url-readme:
|
noti-discord-pre-release-and-update-url-readme:
|
||||||
needs: [build-macos, build-windows-x64, build-linux-x64, get-update-version, set-public-provider]
|
needs: [build-macos-x64, build-macos-arm64, build-windows-x64, build-linux-x64, get-update-version, set-public-provider, combine-latest-mac-yml]
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
if: github.event_name == 'push'
|
if: github.event_name == 'push'
|
||||||
uses: ./.github/workflows/template-noti-discord-and-update-url-readme.yml
|
uses: ./.github/workflows/template-noti-discord-and-update-url-readme.yml
|
||||||
@ -99,7 +151,7 @@ jobs:
|
|||||||
new_version: ${{ needs.get-update-version.outputs.new_version }}
|
new_version: ${{ needs.get-update-version.outputs.new_version }}
|
||||||
|
|
||||||
noti-discord-manual-and-update-url-readme:
|
noti-discord-manual-and-update-url-readme:
|
||||||
needs: [build-macos, build-windows-x64, build-linux-x64, get-update-version, set-public-provider]
|
needs: [build-macos-x64, build-macos-arm64, build-windows-x64, build-linux-x64, get-update-version, set-public-provider, combine-latest-mac-yml]
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
if: github.event_name == 'workflow_dispatch' && github.event.inputs.public_provider == 'cloudflare-r2'
|
if: github.event_name == 'workflow_dispatch' && github.event.inputs.public_provider == 'cloudflare-r2'
|
||||||
uses: ./.github/workflows/template-noti-discord-and-update-url-readme.yml
|
uses: ./.github/workflows/template-noti-discord-and-update-url-readme.yml
|
||||||
|
|||||||
84
.github/workflows/jan-electron-build.yml
vendored
84
.github/workflows/jan-electron-build.yml
vendored
@ -9,8 +9,42 @@ jobs:
|
|||||||
get-update-version:
|
get-update-version:
|
||||||
uses: ./.github/workflows/template-get-update-version.yml
|
uses: ./.github/workflows/template-get-update-version.yml
|
||||||
|
|
||||||
build-macos:
|
create-draft-release:
|
||||||
uses: ./.github/workflows/template-build-macos.yml
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
||||||
|
outputs:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
version: ${{ steps.get_version.outputs.version }}
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- name: Extract tag name without v prefix
|
||||||
|
id: get_version
|
||||||
|
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV && echo "::set-output name=version::${GITHUB_REF#refs/tags/v}"
|
||||||
|
env:
|
||||||
|
GITHUB_REF: ${{ github.ref }}
|
||||||
|
- name: Create Draft Release
|
||||||
|
id: create_release
|
||||||
|
uses: actions/create-release@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
tag_name: ${{ github.ref_name }}
|
||||||
|
release_name: "${{ env.VERSION }}"
|
||||||
|
draft: true
|
||||||
|
prerelease: false
|
||||||
|
|
||||||
|
build-macos-x64:
|
||||||
|
uses: ./.github/workflows/template-build-macos-x64.yml
|
||||||
|
secrets: inherit
|
||||||
|
needs: [get-update-version]
|
||||||
|
with:
|
||||||
|
ref: ${{ github.ref }}
|
||||||
|
public_provider: github
|
||||||
|
new_version: ${{ needs.get-update-version.outputs.new_version }}
|
||||||
|
|
||||||
|
build-macos-arm64:
|
||||||
|
uses: ./.github/workflows/template-build-macos-arm64.yml
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
needs: [get-update-version]
|
needs: [get-update-version]
|
||||||
with:
|
with:
|
||||||
@ -36,8 +70,52 @@ jobs:
|
|||||||
public_provider: github
|
public_provider: github
|
||||||
new_version: ${{ needs.get-update-version.outputs.new_version }}
|
new_version: ${{ needs.get-update-version.outputs.new_version }}
|
||||||
|
|
||||||
|
combine-latest-mac-yml:
|
||||||
|
needs: [build-macos-x64, build-macos-arm64, create-draft-release]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- name: Getting the repo
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Download mac-x64 artifacts
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: latest-mac-x64
|
||||||
|
path: ./latest-mac-x64
|
||||||
|
- name: Download mac-arm artifacts
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: latest-mac-arm64
|
||||||
|
path: ./latest-mac-arm64
|
||||||
|
|
||||||
|
- name: 'Merge latest-mac.yml'
|
||||||
|
# unfortunately electron-builder doesn't understand that we have two different releases for mac-x64 and mac-arm, so we need to manually merge the latest files
|
||||||
|
# see https://github.com/electron-userland/electron-builder/issues/5592
|
||||||
|
run: |
|
||||||
|
ls -la .
|
||||||
|
ls -la ./latest-mac-x64
|
||||||
|
ls -la ./latest-mac-arm64
|
||||||
|
ls -la ./electron
|
||||||
|
cp ./electron/merge-latest-ymls.js /tmp/merge-latest-ymls.js
|
||||||
|
npm install js-yaml --prefix /tmp
|
||||||
|
node /tmp/merge-latest-ymls.js ./latest-mac-x64/latest-mac.yml ./latest-mac-arm64/latest-mac.yml ./latest-mac.yml
|
||||||
|
cat ./latest-mac.yml
|
||||||
|
|
||||||
|
- name: Yet Another Upload Release Asset Action
|
||||||
|
uses: shogo82148/actions-upload-release-asset@v1.7.2
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ needs.create-draft-release.outputs.upload_url }}
|
||||||
|
asset_path: ./latest-mac.yml
|
||||||
|
asset_name: latest-mac.yml
|
||||||
|
asset_content_type: text/yaml
|
||||||
|
overwrite: true
|
||||||
|
|
||||||
update_release_draft:
|
update_release_draft:
|
||||||
needs: [build-macos, build-windows-x64, build-linux-x64]
|
needs: [build-macos-x64, build-macos-arm64, build-windows-x64, build-linux-x64, combine-latest-mac-yml]
|
||||||
permissions:
|
permissions:
|
||||||
# write permission is required to create a github release
|
# write permission is required to create a github release
|
||||||
contents: write
|
contents: write
|
||||||
|
|||||||
160
.github/workflows/template-build-macos-arm64.yml
vendored
Normal file
160
.github/workflows/template-build-macos-arm64.yml
vendored
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
name: build-macos
|
||||||
|
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, cloudflare: build and publish to cloudflare'
|
||||||
|
new_version:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
|
cloudflare_r2_path:
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: '/latest/'
|
||||||
|
secrets:
|
||||||
|
CLOUDFLARE_R2_BUCKET_NAME:
|
||||||
|
required: false
|
||||||
|
CLOUDFLARE_R2_ACCESS_KEY_ID:
|
||||||
|
required: false
|
||||||
|
CLOUDFLARE_R2_SECRET_ACCESS_KEY:
|
||||||
|
required: false
|
||||||
|
CLOUDFLARE_ACCOUNT_ID:
|
||||||
|
required: false
|
||||||
|
CODE_SIGN_P12_BASE64:
|
||||||
|
required: false
|
||||||
|
CODE_SIGN_P12_PASSWORD:
|
||||||
|
required: false
|
||||||
|
APPLE_ID:
|
||||||
|
required: false
|
||||||
|
APPLE_APP_SPECIFIC_PASSWORD:
|
||||||
|
required: false
|
||||||
|
DEVELOPER_ID:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-macos:
|
||||||
|
runs-on: macos-silicon
|
||||||
|
environment: production
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- name: Getting the repo
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: ${{ inputs.ref }}
|
||||||
|
|
||||||
|
- name: Installing node
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
- name: Unblock keychain
|
||||||
|
run: |
|
||||||
|
security unlock-keychain -p ${{ secrets.KEYCHAIN_PASSWORD }} ~/Library/Keychains/login.keychain-db
|
||||||
|
# - uses: actions/setup-python@v5
|
||||||
|
# with:
|
||||||
|
# python-version: '3.11'
|
||||||
|
|
||||||
|
# - name: Install jq
|
||||||
|
# uses: dcarbone/install-jq-action@v2.0.1
|
||||||
|
|
||||||
|
- name: Update app version based on latest release tag with build number
|
||||||
|
if: inputs.public_provider != 'github'
|
||||||
|
run: |
|
||||||
|
echo "Version: ${{ inputs.new_version }}"
|
||||||
|
# Update the version in electron/package.json
|
||||||
|
jq --arg version "${{ inputs.new_version }}" '.version = $version' electron/package.json > /tmp/package.json
|
||||||
|
mv /tmp/package.json electron/package.json
|
||||||
|
|
||||||
|
jq --arg version "${{ inputs.new_version }}" '.version = $version' web/package.json > /tmp/package.json
|
||||||
|
mv /tmp/package.json web/package.json
|
||||||
|
|
||||||
|
jq '.build.publish = [{"provider": "generic", "url": "${{ secrets.CLOUDFLARE_R2_PUBLIC_URL }}", "channel": "latest"}, {"provider": "s3", "bucket": "${{ secrets.CLOUDFLARE_R2_BUCKET_NAME }}", "region": "auto", "endpoint": "https://${{ secrets.CLOUDFLARE_ACCOUNT_ID }}.r2.cloudflarestorage.com", "path": "${{ inputs.cloudflare_r2_path }}", "channel": "latest"}]' electron/package.json > /tmp/package.json
|
||||||
|
mv /tmp/package.json electron/package.json
|
||||||
|
cat electron/package.json
|
||||||
|
|
||||||
|
- name: Update app version base on tag
|
||||||
|
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') && inputs.public_provider == 'github'
|
||||||
|
run: |
|
||||||
|
if [[ ! "${VERSION_TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||||
|
echo "Error: Tag is not valid!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
jq --arg version "${VERSION_TAG#v}" '.version = $version' electron/package.json > /tmp/package.json
|
||||||
|
mv /tmp/package.json electron/package.json
|
||||||
|
jq --arg version "${VERSION_TAG#v}" '.version = $version' web/package.json > /tmp/package.json
|
||||||
|
mv /tmp/package.json web/package.json
|
||||||
|
env:
|
||||||
|
VERSION_TAG: ${{ inputs.new_version }}
|
||||||
|
|
||||||
|
# - name: Get Cer for code signing
|
||||||
|
# run: base64 -d <<< "$CODE_SIGN_P12_BASE64" > /tmp/codesign.p12
|
||||||
|
# shell: bash
|
||||||
|
# env:
|
||||||
|
# CODE_SIGN_P12_BASE64: ${{ secrets.CODE_SIGN_P12_BASE64 }}
|
||||||
|
|
||||||
|
# - uses: apple-actions/import-codesign-certs@v2
|
||||||
|
# continue-on-error: true
|
||||||
|
# with:
|
||||||
|
# p12-file-base64: ${{ secrets.CODE_SIGN_P12_BASE64 }}
|
||||||
|
# p12-password: ${{ secrets.CODE_SIGN_P12_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Build and publish app to cloudflare r2 or github artifactory
|
||||||
|
if: inputs.public_provider != 'github'
|
||||||
|
run: |
|
||||||
|
# check public_provider is true or not
|
||||||
|
echo "public_provider is ${{ inputs.public_provider }}"
|
||||||
|
if [ "${{ inputs.public_provider }}" == "none" ]; then
|
||||||
|
make build
|
||||||
|
else
|
||||||
|
make build-and-publish
|
||||||
|
fi
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
# CSC_LINK: "/tmp/codesign.p12"
|
||||||
|
# CSC_KEY_PASSWORD: ${{ secrets.CODE_SIGN_P12_PASSWORD }}
|
||||||
|
# CSC_IDENTITY_AUTO_DISCOVERY: "true"
|
||||||
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||||
|
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
|
||||||
|
APP_PATH: "."
|
||||||
|
DEVELOPER_ID: ${{ secrets.DEVELOPER_ID }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_DEFAULT_REGION: auto
|
||||||
|
AWS_EC2_METADATA_DISABLED: "true"
|
||||||
|
|
||||||
|
- name: Build and publish app to github
|
||||||
|
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') && inputs.public_provider == 'github'
|
||||||
|
run: |
|
||||||
|
make build-and-publish
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
# CSC_LINK: "/tmp/codesign.p12"
|
||||||
|
# CSC_KEY_PASSWORD: ${{ secrets.CODE_SIGN_P12_PASSWORD }}
|
||||||
|
# CSC_IDENTITY_AUTO_DISCOVERY: "true"
|
||||||
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||||
|
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
|
||||||
|
APP_PATH: "."
|
||||||
|
DEVELOPER_ID: ${{ secrets.DEVELOPER_ID }}
|
||||||
|
ANALYTICS_ID: ${{ secrets.JAN_APP_UMAMI_PROJECT_API_KEY }}
|
||||||
|
ANALYTICS_HOST: ${{ secrets.JAN_APP_UMAMI_URL }}
|
||||||
|
|
||||||
|
- name: Upload Artifact
|
||||||
|
if: inputs.public_provider != 'github'
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: jan-mac-arm64-${{ inputs.new_version }}
|
||||||
|
path: ./electron/dist/jan-mac-arm64-${{ inputs.new_version }}.dmg
|
||||||
|
|
||||||
|
- name: Upload Artifact
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: latest-mac-arm64
|
||||||
|
path: ./electron/dist/latest-mac.yml
|
||||||
@ -148,9 +148,8 @@ jobs:
|
|||||||
path: ./electron/dist/jan-mac-x64-${{ inputs.new_version }}.dmg
|
path: ./electron/dist/jan-mac-x64-${{ inputs.new_version }}.dmg
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
if: inputs.public_provider != 'github'
|
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: jan-mac-arm64-${{ inputs.new_version }}
|
name: latest-mac-x64
|
||||||
path: ./electron/dist/jan-mac-arm64-${{ inputs.new_version }}.dmg
|
path: ./electron/dist/latest-mac.yml
|
||||||
|
|
||||||
27
electron/merge-latest-ymls.js
Normal file
27
electron/merge-latest-ymls.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
const yaml = require('js-yaml')
|
||||||
|
const fs = require('fs')
|
||||||
|
|
||||||
|
// get two file paths from arguments:
|
||||||
|
const [, , ...args] = process.argv
|
||||||
|
const file1 = args[0]
|
||||||
|
const file2 = args[1]
|
||||||
|
const file3 = args[2]
|
||||||
|
|
||||||
|
// check that all arguments are present and throw error instead
|
||||||
|
if (!file1 || !file2 || !file3) {
|
||||||
|
throw new Error('Please provide 3 file paths as arguments: path to file1, to file2 and destination path')
|
||||||
|
}
|
||||||
|
|
||||||
|
const doc1 = yaml.load(fs.readFileSync(file1, 'utf8'))
|
||||||
|
console.log('doc1: ', doc1)
|
||||||
|
|
||||||
|
const doc2 = yaml.load(fs.readFileSync(file2, 'utf8'))
|
||||||
|
console.log('doc2: ', doc2)
|
||||||
|
|
||||||
|
const merged = { ...doc1, ...doc2 }
|
||||||
|
merged.files.push(...doc1.files)
|
||||||
|
|
||||||
|
console.log('merged', merged)
|
||||||
|
|
||||||
|
const mergedYml = yaml.dump(merged)
|
||||||
|
fs.writeFileSync(file3, mergedYml, 'utf8')
|
||||||
@ -63,11 +63,11 @@
|
|||||||
"build:test:darwin": "tsc -p . && electron-builder -p never -m --dir",
|
"build:test:darwin": "tsc -p . && electron-builder -p never -m --dir",
|
||||||
"build:test:win32": "tsc -p . && electron-builder -p never -w --dir",
|
"build:test:win32": "tsc -p . && electron-builder -p never -w --dir",
|
||||||
"build:test:linux": "tsc -p . && electron-builder -p never -l --dir",
|
"build:test:linux": "tsc -p . && electron-builder -p never -l --dir",
|
||||||
"build:darwin": "tsc -p . && electron-builder -p never -m --x64 --arm64",
|
"build:darwin": "tsc -p . && electron-builder -p never -m",
|
||||||
"build:win32": "tsc -p . && electron-builder -p never -w",
|
"build:win32": "tsc -p . && electron-builder -p never -w",
|
||||||
"build:linux": "tsc -p . && electron-builder -p never -l deb -l AppImage",
|
"build:linux": "tsc -p . && electron-builder -p never -l deb -l AppImage",
|
||||||
"build:publish": "run-script-os",
|
"build:publish": "run-script-os",
|
||||||
"build:publish:darwin": "tsc -p . && electron-builder -p always -m --x64 --arm64",
|
"build:publish:darwin": "tsc -p . && electron-builder -p always -m",
|
||||||
"build:publish:win32": "tsc -p . && electron-builder -p always -w",
|
"build:publish:win32": "tsc -p . && electron-builder -p always -w",
|
||||||
"build:publish:linux": "tsc -p . && electron-builder -p always -l deb -l AppImage"
|
"build:publish:linux": "tsc -p . && electron-builder -p always -l deb -l AppImage"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -35,21 +35,19 @@ export class Retrieval {
|
|||||||
if (engine === "nitro") {
|
if (engine === "nitro") {
|
||||||
this.embeddingModel = new OpenAIEmbeddings(
|
this.embeddingModel = new OpenAIEmbeddings(
|
||||||
{ openAIApiKey: "nitro-embedding" },
|
{ openAIApiKey: "nitro-embedding" },
|
||||||
{ basePath: "http://127.0.0.1:3928/v1" }
|
{ basePath: "http://127.0.0.1:3928/v1" },
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Fallback to OpenAI Settings
|
// Fallback to OpenAI Settings
|
||||||
this.embeddingModel = new OpenAIEmbeddings({
|
this.embeddingModel = new OpenAIEmbeddings({
|
||||||
configuration: {
|
openAIApiKey: settings.api_key,
|
||||||
apiKey: settings.api_key,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ingestAgentKnowledge = async (
|
public ingestAgentKnowledge = async (
|
||||||
filePath: string,
|
filePath: string,
|
||||||
memoryPath: string
|
memoryPath: string,
|
||||||
): Promise<any> => {
|
): Promise<any> => {
|
||||||
const loader = new PDFLoader(filePath, {
|
const loader = new PDFLoader(filePath, {
|
||||||
splitPages: true,
|
splitPages: true,
|
||||||
|
|||||||
@ -243,9 +243,6 @@ export default class JanInferenceNitroExtension extends InferenceExtension {
|
|||||||
*/
|
*/
|
||||||
private async onMessageRequest(data: MessageRequest) {
|
private async onMessageRequest(data: MessageRequest) {
|
||||||
if (data.model?.engine !== InferenceEngine.nitro || !this._currentModel) {
|
if (data.model?.engine !== InferenceEngine.nitro || !this._currentModel) {
|
||||||
console.log(
|
|
||||||
`Model is not nitro or no model loaded ${data.model?.engine} ${this._currentModel}`
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -286,6 +286,7 @@ export default class JanModelExtension extends ModelExtension {
|
|||||||
* model.json file associated with it.
|
* model.json file associated with it.
|
||||||
*
|
*
|
||||||
* This function will create a model.json file for the model.
|
* This function will create a model.json file for the model.
|
||||||
|
* It works only with single binary file model.
|
||||||
*
|
*
|
||||||
* @param dirName the director which reside in ~/jan/models but does not have model.json file.
|
* @param dirName the director which reside in ~/jan/models but does not have model.json file.
|
||||||
*/
|
*/
|
||||||
@ -302,15 +303,14 @@ export default class JanModelExtension extends ModelExtension {
|
|||||||
let binaryFileSize: number | undefined = undefined
|
let binaryFileSize: number | undefined = undefined
|
||||||
|
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
if (file.endsWith(JanModelExtension._incompletedModelFileName)) continue
|
if (file.endsWith(JanModelExtension._supportedModelFormat)) {
|
||||||
if (file.endsWith('.json')) continue
|
const path = await joinPath([JanModelExtension._homeDir, dirName, file])
|
||||||
|
const fileStats = await fs.fileStat(path)
|
||||||
const path = await joinPath([JanModelExtension._homeDir, dirName, file])
|
if (fileStats.isDirectory) continue
|
||||||
const fileStats = await fs.fileStat(path)
|
binaryFileSize = fileStats.size
|
||||||
if (fileStats.isDirectory) continue
|
binaryFileName = file
|
||||||
binaryFileSize = fileStats.size
|
break
|
||||||
binaryFileName = file
|
}
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!binaryFileName) {
|
if (!binaryFileName) {
|
||||||
@ -318,7 +318,7 @@ export default class JanModelExtension extends ModelExtension {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultModel = await this.getDefaultModel()
|
const defaultModel = await this.getDefaultModel() as Model
|
||||||
if (!defaultModel) {
|
if (!defaultModel) {
|
||||||
console.error('Unable to find default model')
|
console.error('Unable to find default model')
|
||||||
return
|
return
|
||||||
@ -326,8 +326,19 @@ export default class JanModelExtension extends ModelExtension {
|
|||||||
|
|
||||||
const model: Model = {
|
const model: Model = {
|
||||||
...defaultModel,
|
...defaultModel,
|
||||||
|
// Overwrite default N/A fields
|
||||||
id: dirName,
|
id: dirName,
|
||||||
name: dirName,
|
name: dirName,
|
||||||
|
sources: [
|
||||||
|
{
|
||||||
|
url: binaryFileName,
|
||||||
|
filename: binaryFileName,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
settings: {
|
||||||
|
...defaultModel.settings,
|
||||||
|
llama_model_path: binaryFileName,
|
||||||
|
},
|
||||||
created: Date.now(),
|
created: Date.now(),
|
||||||
description: `${dirName} - user self import model`,
|
description: `${dirName} - user self import model`,
|
||||||
metadata: {
|
metadata: {
|
||||||
|
|||||||
@ -21,6 +21,8 @@ import {
|
|||||||
|
|
||||||
import Umami from '@/utils/umami'
|
import Umami from '@/utils/umami'
|
||||||
|
|
||||||
|
import Loader from '../Loader'
|
||||||
|
|
||||||
import KeyListener from './KeyListener'
|
import KeyListener from './KeyListener'
|
||||||
|
|
||||||
import { extensionManager } from '@/extension'
|
import { extensionManager } from '@/extension'
|
||||||
@ -30,6 +32,7 @@ const Providers = (props: PropsWithChildren) => {
|
|||||||
|
|
||||||
const [setupCore, setSetupCore] = useState(false)
|
const [setupCore, setSetupCore] = useState(false)
|
||||||
const [activated, setActivated] = useState(false)
|
const [activated, setActivated] = useState(false)
|
||||||
|
const [settingUp, setSettingUp] = useState(false)
|
||||||
|
|
||||||
async function setupExtensions() {
|
async function setupExtensions() {
|
||||||
// Register all active extensions
|
// Register all active extensions
|
||||||
@ -37,11 +40,13 @@ const Providers = (props: PropsWithChildren) => {
|
|||||||
|
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
if (!isCoreExtensionInstalled()) {
|
if (!isCoreExtensionInstalled()) {
|
||||||
setupBaseExtensions()
|
setSettingUp(true)
|
||||||
|
await setupBaseExtensions()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
extensionManager.load()
|
extensionManager.load()
|
||||||
|
setSettingUp(false)
|
||||||
setActivated(true)
|
setActivated(true)
|
||||||
}, 500)
|
}, 500)
|
||||||
}
|
}
|
||||||
@ -71,6 +76,7 @@ const Providers = (props: PropsWithChildren) => {
|
|||||||
<JotaiWrapper>
|
<JotaiWrapper>
|
||||||
<ThemeWrapper>
|
<ThemeWrapper>
|
||||||
<Umami />
|
<Umami />
|
||||||
|
{settingUp && <Loader description="Preparing Update..." />}
|
||||||
{setupCore && activated && (
|
{setupCore && activated && (
|
||||||
<KeyListener>
|
<KeyListener>
|
||||||
<FeatureToggleWrapper>
|
<FeatureToggleWrapper>
|
||||||
|
|||||||
@ -8,6 +8,8 @@ import {
|
|||||||
|
|
||||||
import { useAtomValue, useSetAtom } from 'jotai'
|
import { useAtomValue, useSetAtom } from 'jotai'
|
||||||
|
|
||||||
|
import { loadModelErrorAtom } from './useActiveModel'
|
||||||
|
|
||||||
import { extensionManager } from '@/extension'
|
import { extensionManager } from '@/extension'
|
||||||
import { setConvoMessagesAtom } from '@/helpers/atoms/ChatMessage.atom'
|
import { setConvoMessagesAtom } from '@/helpers/atoms/ChatMessage.atom'
|
||||||
import {
|
import {
|
||||||
@ -24,6 +26,7 @@ export default function useSetActiveThread() {
|
|||||||
const setThreadMessage = useSetAtom(setConvoMessagesAtom)
|
const setThreadMessage = useSetAtom(setConvoMessagesAtom)
|
||||||
const setThreadModelParams = useSetAtom(setThreadModelParamsAtom)
|
const setThreadModelParams = useSetAtom(setThreadModelParamsAtom)
|
||||||
const setIsGeneratingResponse = useSetAtom(isGeneratingResponseAtom)
|
const setIsGeneratingResponse = useSetAtom(isGeneratingResponseAtom)
|
||||||
|
const setLoadModelError = useSetAtom(loadModelErrorAtom)
|
||||||
|
|
||||||
const setActiveThread = async (thread: Thread) => {
|
const setActiveThread = async (thread: Thread) => {
|
||||||
if (activeThreadId === thread.id) {
|
if (activeThreadId === thread.id) {
|
||||||
@ -32,6 +35,7 @@ export default function useSetActiveThread() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setIsGeneratingResponse(false)
|
setIsGeneratingResponse(false)
|
||||||
|
setLoadModelError(undefined)
|
||||||
events.emit(InferenceEvent.OnInferenceStopped, thread.id)
|
events.emit(InferenceEvent.OnInferenceStopped, thread.id)
|
||||||
|
|
||||||
// load the corresponding messages
|
// load the corresponding messages
|
||||||
|
|||||||
@ -25,7 +25,6 @@ const ChatBody: React.FC = () => {
|
|||||||
const messages = useAtomValue(getCurrentChatMessagesAtom)
|
const messages = useAtomValue(getCurrentChatMessagesAtom)
|
||||||
const { downloadedModels } = useGetDownloadedModels()
|
const { downloadedModels } = useGetDownloadedModels()
|
||||||
const { setMainViewState } = useMainViewState()
|
const { setMainViewState } = useMainViewState()
|
||||||
const loadModelError = useAtomValue(loadModelErrorAtom)
|
|
||||||
|
|
||||||
if (downloadedModels.length === 0)
|
if (downloadedModels.length === 0)
|
||||||
return (
|
return (
|
||||||
@ -86,9 +85,8 @@ const ChatBody: React.FC = () => {
|
|||||||
message.content.length > 0) && (
|
message.content.length > 0) && (
|
||||||
<ChatItem {...message} key={message.id} />
|
<ChatItem {...message} key={message.id} />
|
||||||
)}
|
)}
|
||||||
{!loadModelError &&
|
{(message.status === MessageStatus.Error ||
|
||||||
(message.status === MessageStatus.Error ||
|
message.status === MessageStatus.Stopped) &&
|
||||||
message.status === MessageStatus.Stopped) &&
|
|
||||||
index === messages.length - 1 && (
|
index === messages.length - 1 && (
|
||||||
<ErrorMessage message={message} />
|
<ErrorMessage message={message} />
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -1,48 +0,0 @@
|
|||||||
import { MessageStatus, ThreadMessage } from '@janhq/core'
|
|
||||||
import { useAtomValue } from 'jotai'
|
|
||||||
|
|
||||||
import { useActiveModel } from '@/hooks/useActiveModel'
|
|
||||||
|
|
||||||
import { totalRamAtom } from '@/helpers/atoms/SystemBar.atom'
|
|
||||||
|
|
||||||
const LoadModelErrorMessage = () => {
|
|
||||||
const { activeModel } = useActiveModel()
|
|
||||||
const availableRam = useAtomValue(totalRamAtom)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="mt-10 flex flex-col items-center">
|
|
||||||
<span className="mb-3 text-center text-sm font-medium text-gray-500">
|
|
||||||
{Number(activeModel?.metadata.size) > availableRam ? (
|
|
||||||
<>
|
|
||||||
Oops! Model size exceeds available RAM. Consider selecting a
|
|
||||||
smaller model or upgrading your RAM for smoother performance.
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<p>Apologies, something's amiss!</p>
|
|
||||||
Jan's in beta. Find troubleshooting guides{' '}
|
|
||||||
<a
|
|
||||||
href="https://jan.ai/guides/troubleshooting"
|
|
||||||
target="_blank"
|
|
||||||
className="text-blue-600 hover:underline dark:text-blue-300"
|
|
||||||
>
|
|
||||||
here
|
|
||||||
</a>{' '}
|
|
||||||
or reach out to us on{' '}
|
|
||||||
<a
|
|
||||||
href="https://discord.gg/AsJ8krTT3N"
|
|
||||||
target="_blank"
|
|
||||||
className="text-blue-600 hover:underline dark:text-blue-300"
|
|
||||||
>
|
|
||||||
Discord
|
|
||||||
</a>{' '}
|
|
||||||
for assistance.
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default LoadModelErrorMessage
|
|
||||||
@ -20,7 +20,7 @@ import { snackbar } from '@/containers/Toast'
|
|||||||
|
|
||||||
import { FeatureToggleContext } from '@/context/FeatureToggle'
|
import { FeatureToggleContext } from '@/context/FeatureToggle'
|
||||||
|
|
||||||
import { activeModelAtom, loadModelErrorAtom } from '@/hooks/useActiveModel'
|
import { activeModelAtom } from '@/hooks/useActiveModel'
|
||||||
import { queuedMessageAtom, reloadModelAtom } from '@/hooks/useSendChatMessage'
|
import { queuedMessageAtom, reloadModelAtom } from '@/hooks/useSendChatMessage'
|
||||||
|
|
||||||
import ChatBody from '@/screens/Chat/ChatBody'
|
import ChatBody from '@/screens/Chat/ChatBody'
|
||||||
@ -28,7 +28,6 @@ import ChatBody from '@/screens/Chat/ChatBody'
|
|||||||
import ThreadList from '@/screens/Chat/ThreadList'
|
import ThreadList from '@/screens/Chat/ThreadList'
|
||||||
|
|
||||||
import ChatInput from './ChatInput'
|
import ChatInput from './ChatInput'
|
||||||
import LoadModelErrorMessage from './LoadModelErrorMessage'
|
|
||||||
import RequestDownloadModel from './RequestDownloadModel'
|
import RequestDownloadModel from './RequestDownloadModel'
|
||||||
import Sidebar from './Sidebar'
|
import Sidebar from './Sidebar'
|
||||||
|
|
||||||
@ -70,7 +69,6 @@ const ChatScreen: React.FC = () => {
|
|||||||
const activeModel = useAtomValue(activeModelAtom)
|
const activeModel = useAtomValue(activeModelAtom)
|
||||||
|
|
||||||
const isGeneratingResponse = useAtomValue(isGeneratingResponseAtom)
|
const isGeneratingResponse = useAtomValue(isGeneratingResponseAtom)
|
||||||
const loadModelError = useAtomValue(loadModelErrorAtom)
|
|
||||||
|
|
||||||
const { getRootProps, isDragReject } = useDropzone({
|
const { getRootProps, isDragReject } = useDropzone({
|
||||||
noClick: true,
|
noClick: true,
|
||||||
@ -213,7 +211,6 @@ const ChatScreen: React.FC = () => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{activeModel && isGeneratingResponse && <GenerateResponse />}
|
{activeModel && isGeneratingResponse && <GenerateResponse />}
|
||||||
{loadModelError && <LoadModelErrorMessage />}
|
|
||||||
<ChatInput />
|
<ChatInput />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -109,10 +109,10 @@ const Advanced = () => {
|
|||||||
<div className="flex w-full items-start justify-between border-b border-border py-4 first:pt-0 last:border-none">
|
<div className="flex w-full items-start justify-between border-b border-border py-4 first:pt-0 last:border-none">
|
||||||
<div className="flex-shrink-0 space-y-1.5">
|
<div className="flex-shrink-0 space-y-1.5">
|
||||||
<div className="flex gap-x-2">
|
<div className="flex gap-x-2">
|
||||||
<h6 className="text-sm font-semibold capitalize">NVidia GPU</h6>
|
<h6 className="text-sm font-semibold capitalize">Nvidia GPU</h6>
|
||||||
</div>
|
</div>
|
||||||
<p className="leading-relaxed">
|
<p className="leading-relaxed">
|
||||||
Enable GPU acceleration for NVidia GPUs.
|
Enable GPU acceleration for Nvidia GPUs.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Switch
|
<Switch
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user