diff --git a/.github/workflows/cortex-cpp-build.yml b/.github/workflows/cortex-build.yml similarity index 71% rename from .github/workflows/cortex-cpp-build.yml rename to .github/workflows/cortex-build.yml index e3eb1653a..f6f4dbe27 100644 --- a/.github/workflows/cortex-cpp-build.yml +++ b/.github/workflows/cortex-build.yml @@ -3,10 +3,7 @@ name: CI Cortex CPP on: push: tags: ["v[0-9]+.[0-9]+.[0-9]+"] - paths: - [ - "cortex-cpp/**", - ] + paths: ["cortex-cpp/**", "cortex-js/**"] workflow_dispatch: env: @@ -201,7 +198,7 @@ jobs: shell: bash env: CODE_SIGN_P12_BASE64: ${{ secrets.CODE_SIGN_P12_BASE64 }} - + - uses: apple-actions/import-codesign-certs@v2 if: runner.os == 'macOS' with: @@ -265,8 +262,132 @@ jobs: asset_name: cortex-cpp-${{ needs.create-draft-release.outputs.version }}-${{ matrix.os }}-${{ matrix.name }}.tar.gz asset_content_type: application/gzip + build-cortex-single-binary: + runs-on: ${{ matrix.runs-on }} + needs: [create-draft-release] + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + include: + - os: "linux" + name: "amd64" + runs-on: "ubuntu-latest" + + - os: "windows" + name: "amd64" + runs-on: "windows-latest" + + - os: "mac" + name: "amd64" + runs-on: "macos-13" + + - os: "mac" + name: "arm64" + runs-on: "macos-latest" + steps: + - name: Clone + id: checkout + uses: actions/checkout@v3 + with: + submodules: recursive + + - uses: actions/setup-dotnet@v3 + if: runner.os == 'Windows' + with: + dotnet-version: "8.0.x" + + - name: Install choco on Windows + if: runner.os == 'Windows' + run: | + choco install make -y + + - uses: actions/setup-node@v3 + with: + node-version: "20.x" + registry-url: "https://registry.npmjs.org" + + - run: npm install -g yarn + + - run: yarn install && yarn build && yarn build:binary + working-directory: ./cortex-js + + - name: Get Cer for code signing + if: runner.os == 'macOS' + 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 + if: runner.os == 'macOS' + with: + p12-file-base64: ${{ secrets.CODE_SIGN_P12_BASE64 }} + p12-password: ${{ secrets.CODE_SIGN_P12_PASSWORD }} + + - name: Code Signing macOS + if: runner.os == 'macOS' + run: | + cd cortex-js + make codesign CODE_SIGN=true DEVELOPER_ID="${{ secrets.DEVELOPER_ID }}" + + - name: Compile .ISS to .EXE Installer + uses: Minionguyjpro/Inno-Setup-Action@v1.2.2 + if: runner.os == 'Windows' + with: + path: cortex-js/installer.iss + options: /O+ + + - uses: nick-fields/retry@v3 + with: + continue_on_error: true + retry_wait_seconds: 10 + timeout_minutes: 10 + max_attempts: 3 + shell: cmd + command: | + cd cortex-js + set PATH=%PATH%;%USERPROFILE%\.dotnet\tools + make codesign CODE_SIGN=true AZURE_KEY_VAULT_URI="${{ secrets.AZURE_KEY_VAULT_URI }}" AZURE_CLIENT_ID="${{ secrets.AZURE_CLIENT_ID }}" AZURE_TENANT_ID="${{ secrets.AZURE_TENANT_ID }}" AZURE_CLIENT_SECRET="${{ secrets.AZURE_CLIENT_SECRET }}" AZURE_CERT_NAME="${{ secrets.AZURE_CERT_NAME }}" + name: Code Signing Windows + if: runner.os == 'Windows' + + - name: Post-Bundle + run: | + cd cortex-js + make postbundle + + - name: Upload Artifact + uses: actions/upload-artifact@v2 + with: + name: cortex-${{ matrix.os }}-${{ matrix.name }} + path: | + ./cortex-js/cortex + ./cortex-js/cortex.exe + ./cortex-js/setup.exe + + - name: Upload Cortex Windows Installer + uses: actions/upload-release-asset@v1.0.1 + if: runner.os == 'Windows' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ needs.create-draft-release.outputs.upload_url }} + asset_path: ./cortex-js/cortex-installer.tar.gz + asset_name: cortex-installer-${{ needs.create-draft-release.outputs.version }}-${{ matrix.name }}-${{ matrix.os }}.tar.gz + asset_content_type: application/gzip + + - uses: actions/upload-release-asset@v1.0.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ needs.create-draft-release.outputs.upload_url }} + asset_path: ./cortex-js/cortex.tar.gz + asset_name: cortex-${{ needs.create-draft-release.outputs.version }}-${{ matrix.name }}-${{ matrix.os }}.tar.gz + asset_content_type: application/gzip + update_release_draft: - needs: [build-and-test] + needs: [build-and-test, build-cortex-single-binary] permissions: # write permission is required to create a github release contents: write @@ -287,4 +408,4 @@ jobs: # config-name: my-config.yml # disable-autolabeler: true env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/cortex-js/Makefile b/cortex-js/Makefile new file mode 100644 index 000000000..9d53d6b8d --- /dev/null +++ b/cortex-js/Makefile @@ -0,0 +1,41 @@ +CODE_SIGN ?= false +AZURE_KEY_VAULT_URI ?= xxxx +AZURE_CLIENT_ID ?= xxxx +AZURE_TENANT_ID ?= xxxx +AZURE_CLIENT_SECRET ?= xxxx +AZURE_CERT_NAME ?= xxxx +DEVELOPER_ID ?= xxxx + +postbundle: +ifeq ($(RUN_TESTS),false) + @echo "Skipping tests" + @exit 0 +endif +ifeq ($(OS),Windows_NT) + @powershell -Command "7z a -ttar temp.tar cortex.exe; 7z a -tgzip cortex.tar.gz temp.tar;" + @powershell -Command "7z a -ttar temp2.tar setup.exe; 7z a -tgzip cortex-installer.tar.gz temp2.tar;" +else ifeq ($(shell uname -s),Linux) + @chmod +x cortex; + tar -czvf cortex.tar.gz cortex; +else + @chmod +x cortex; + tar -czvf cortex.tar.gz cortex; +endif + + +codesign: +ifeq ($(CODE_SIGN),false) + @echo "Skipping Code Sign" + @exit 0 +endif + +ifeq ($(OS),Windows_NT) + @powershell -Command "dotnet tool install --global AzureSignTool;" + @powershell -Command 'azuresigntool.exe sign -kvu "$(AZURE_KEY_VAULT_URI)" -kvi "$(AZURE_CLIENT_ID)" -kvt "$(AZURE_TENANT_ID)" -kvs "$(AZURE_CLIENT_SECRET)" -kvc "$(AZURE_CERT_NAME)" -tr http://timestamp.globalsign.com/tsa/r6advanced1 -v ".\cortex-js\cortex.exe";' + @powershell -Command 'azuresigntool.exe sign -kvu "$(AZURE_KEY_VAULT_URI)" -kvi "$(AZURE_CLIENT_ID)" -kvt "$(AZURE_TENANT_ID)" -kvs "$(AZURE_CLIENT_SECRET)" -kvc "$(AZURE_CERT_NAME)" -tr http://timestamp.globalsign.com/tsa/r6advanced1 -v ".\cortex-js\setup.exe";' +else ifeq ($(shell uname -s),Linux) + @echo "Skipping Code Sign for linux" + @exit 0 +else + find "cortex" -type f -exec codesign --force -s "$(DEVELOPER_ID)" --options=runtime {} \; +endif \ No newline at end of file diff --git a/cortex-js/cortex.ico b/cortex-js/cortex.ico new file mode 100644 index 000000000..d9498120a Binary files /dev/null and b/cortex-js/cortex.ico differ diff --git a/cortex-js/installer.iss b/cortex-js/installer.iss new file mode 100644 index 000000000..96fc8f4de --- /dev/null +++ b/cortex-js/installer.iss @@ -0,0 +1,40 @@ +; Inno Setup Script +; Define the application name, version, and other details +[Setup] +AppName=Cortex +AppVersion=1.0 +DefaultDirName={pf}\Cortex +DefaultGroupName=Cortex +OutputDir=. +OutputBaseFilename=setup +Compression=lzma +SolidCompression=yes +PrivilegesRequired=admin + +; Define the languages section +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" + +; Define the files to be installed +[Files] +Source: "cortex.exe"; DestDir: "{app}"; Flags: ignoreversion + +; Define the icons to be created +[Icons] +Name: "{group}\Cortex"; Filename: "{app}\cortex.exe" + +; Define the run section to execute the application after installation +[Run] +Filename: "cmd"; Parameters: "/c setx PATH ""%PATH%;{app}"""; StatusMsg: "Updating system PATH environment variable..."; Flags: runhidden +Filename: "cmd"; Parameters: "/c cortex init"; StatusMsg: "Initializing Cortex..."; Flags: runhidden waituntilterminated +Filename: "{app}\cortex.exe"; Description: "{cm:LaunchProgram,Cortex}"; Flags: nowait postinstall skipifsilent + +; Define the tasks section (optional, for additional tasks like creating desktop icons) +[Tasks] +Name: "desktopicon"; Description: "Create a &desktop icon"; GroupDescription: "Additional icons:"; Flags: unchecked +Name: "quicklaunchicon"; Description: "Create a &Quick Launch icon"; GroupDescription: "Additional icons:"; Flags: unchecked + +; Define icons for the additional tasks +[Icons] +Name: "{commondesktop}\Cortex"; Filename: "{app}\cortex.exe"; Tasks: desktopicon +Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\Cortex"; Filename: "{app}\cortex.exe"; Tasks: quicklaunchicon diff --git a/cortex-js/package.json b/cortex-js/package.json index 4d6ea116b..366c450dd 100644 --- a/cortex-js/package.json +++ b/cortex-js/package.json @@ -11,7 +11,10 @@ "scripts": { "dev": "nest dev", "build": "yarn build:extensions && nest build && cpx \"cpuinfo/bin/**\" dist/bin", - "build:binary": "yarn build && nexe dist/src/command.js --build --python=$(which python3) -o dist/cortex", + "build:binary": "run-script-os", + "build:binary:windows": "bun build --compile --target=bun-windows-x64 ./dist/src/command.js --outfile cortex.exe --external @nestjs/microservices --external @nestjs/websockets/socket-module --external class-transformer/storage", + "build:binary:linux": "bun build --compile --target=bun-linux-x64 ./dist/src/command.js --outfile cortex --external @nestjs/microservices --external @nestjs/websockets/socket-module --external class-transformer/storage", + "build:binary:macos": "bun build --compile --target=bun-darwin-arm64 ./dist/src/command.js --outfile cortex --external @nestjs/microservices --external @nestjs/websockets/socket-module --external class-transformer/storage", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", "build:extensions": "run-script-os", "build:extensions:windows": "powershell -command \"$jobs = Get-ChildItem -Path './src/extensions' -Directory | ForEach-Object { Start-Job -Name ($_.Name) -ScriptBlock { param($_dir); try { Set-Location $_dir; yarn; yarn build; Write-Output 'Build successful in ' + $_dir } catch { Write-Error 'Error in ' + $_dir; throw } } -ArgumentList $_.FullName }; $jobs | Wait-Job; $jobs | ForEach-Object { Receive-Job -Job $_ -Keep } | ForEach-Object { Write-Host $_ }; $failed = $jobs | Where-Object { $_.State -ne 'Completed' -or $_.ChildJobs[0].JobStateInfo.State -ne 'Completed' }; if ($failed) { Exit 1 }\"", @@ -29,7 +32,7 @@ "test:e2e": "jest --config ./test/jest-e2e.json", "typeorm": "typeorm-ts-node-esm", "build:dev": "npx nest build && chmod +x ./dist/src/command.js && npm link", - "postinstall": "cortex init -s || true" + "postinstall": "patch-package" }, "dependencies": { "@huggingface/gguf": "^0.1.5", @@ -55,12 +58,10 @@ "readline": "^1.3.0", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.1", - "sqlite": "^5.1.1", "sqlite3": "^5.1.7", "systeminformation": "^5.22.11", "typeorm": "^0.3.20", "ulid": "^2.3.0", - "update-notifier": "^5.0.0", "uuid": "^9.0.1", "yaml": "^2.4.2" }, @@ -80,6 +81,7 @@ "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", + "bun": "^1.1.15", "cpx": "^1.5.0", "eslint": "^8.42.0", "eslint-config-prettier": "^9.0.0", @@ -88,7 +90,7 @@ "is-primitive": "^3.0.1", "jest": "^29.5.0", "nest-commander-testing": "^3.3.0", - "nexe": "^4.0.0-rc.6", + "patch-package": "^8.0.0", "prettier": "^3.0.0", "run-script-os": "^1.1.6", "source-map-support": "^0.5.21", diff --git a/cortex-js/patches/sqlite3+5.1.7.patch b/cortex-js/patches/sqlite3+5.1.7.patch new file mode 100644 index 000000000..fc72a4d4d --- /dev/null +++ b/cortex-js/patches/sqlite3+5.1.7.patch @@ -0,0 +1,15 @@ +diff --git a/node_modules/sqlite3/.DS_Store b/node_modules/sqlite3/.DS_Store +new file mode 100644 +index 0000000..10f4d43 +Binary files /dev/null and b/node_modules/sqlite3/.DS_Store differ +diff --git a/node_modules/sqlite3/lib/sqlite3.js b/node_modules/sqlite3/lib/sqlite3.js +index 430a2b8..9df0857 100644 +--- a/node_modules/sqlite3/lib/sqlite3.js ++++ b/node_modules/sqlite3/lib/sqlite3.js +@@ -1,5 +1,5 @@ + const path = require('path'); +-const sqlite3 = require('./sqlite3-binding.js'); ++const sqlite3 = require('./../build/Release/node_sqlite3.node'); + const EventEmitter = require('events').EventEmitter; + module.exports = exports = sqlite3; + diff --git a/cortex-js/src/command.ts b/cortex-js/src/command.ts index 402ac5147..03096560c 100644 --- a/cortex-js/src/command.ts +++ b/cortex-js/src/command.ts @@ -1,8 +1,6 @@ #!/usr/bin/env node import { CommandFactory } from 'nest-commander'; import { CommandModule } from './command.module'; -import updateNotifier from 'update-notifier'; -import packageJson from './../package.json'; import { TelemetryUsecases } from './usecases/telemetry/telemetry.usecases'; import { TelemetrySource } from './domain/telemetry/telemetry.interface'; import { AsyncLocalStorage } from 'async_hooks'; @@ -34,15 +32,6 @@ async function bootstrap() { contextService!.set('source', TelemetrySource.CLI); return CommandFactory.runApplication(app); }); - - const notifier = updateNotifier({ - pkg: packageJson, - updateCheckInterval: 1000 * 60 * 60, // 1 hour - shouldNotifyInNpmScript: true, - }); - notifier.notify({ - isGlobal: true, - }); } bootstrap(); diff --git a/cortex-js/src/infrastructure/commanders/usecases/chat.cli.usecases.ts b/cortex-js/src/infrastructure/commanders/usecases/chat.cli.usecases.ts index f51b00f3c..4990a4073 100644 --- a/cortex-js/src/infrastructure/commanders/usecases/chat.cli.usecases.ts +++ b/cortex-js/src/infrastructure/commanders/usecases/chat.cli.usecases.ts @@ -257,9 +257,6 @@ export class ChatCliUsecases { const model = await this.modelsUsecases.findOne(modelId); if (!model) throw new Error(`Cannot find model with id: ${modelId}`); - const assistant = await this.assistantUsecases.findOne('jan'); - if (!assistant) throw new Error('No assistant available'); - const assistantDto: CreateThreadAssistantDto = { avatar: '', id: 'jan', diff --git a/cortex-js/src/infrastructure/commanders/usecases/init.cli.usecases.ts b/cortex-js/src/infrastructure/commanders/usecases/init.cli.usecases.ts index 5c8fda51c..57ada02c1 100644 --- a/cortex-js/src/infrastructure/commanders/usecases/init.cli.usecases.ts +++ b/cortex-js/src/infrastructure/commanders/usecases/init.cli.usecases.ts @@ -1,11 +1,4 @@ -import { - cpSync, - createWriteStream, - existsSync, - readdir, - readdirSync, - rmSync, -} from 'fs'; +import { cpSync, createWriteStream, existsSync, readdirSync, rmSync } from 'fs'; import { delimiter, join } from 'path'; import { HttpService } from '@nestjs/axios'; import { Presets, SingleBar } from 'cli-progress'; @@ -298,7 +291,7 @@ export class InitCliUsecases { /** * Download and install ONNX engine * @param version - * @param engineFileName + * @param engineFileName */ async installONNXEngine( version: string = 'latest', diff --git a/cortex-js/src/infrastructure/repositories/extensions/extension.repository.ts b/cortex-js/src/infrastructure/repositories/extensions/extension.repository.ts index 389e5f371..ef6ab4fde 100644 --- a/cortex-js/src/infrastructure/repositories/extensions/extension.repository.ts +++ b/cortex-js/src/infrastructure/repositories/extensions/extension.repository.ts @@ -14,6 +14,7 @@ export class ExtensionRepositoryImpl implements ExtensionRepository { extensions = new Map([ ['cortex.llamacpp', this.cortexProvider], ['cortex.onnx', this.cortexProvider], + ['cortex.tensorrt-llm', this.cortexProvider], ]); constructor(