diff --git a/.github/workflows/update-nix-sources.yml b/.github/workflows/update-nix-sources.yml new file mode 100644 index 00000000..c9449eab --- /dev/null +++ b/.github/workflows/update-nix-sources.yml @@ -0,0 +1,79 @@ +name: Update Nix sources + +on: + release: + types: [published] + workflow_dispatch: + inputs: + tag: + description: "Release tag (e.g. v0.6.6)" + required: true + +jobs: + update: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + + steps: + - uses: actions/checkout@v6 + + - name: Normalize tag + id: tag + env: + RAW_TAG: ${{ github.event.release.tag_name || github.event.inputs.tag }} + run: | + case "$RAW_TAG" in + v*) TAG="$RAW_TAG" ;; + *) TAG="v$RAW_TAG" ;; + esac + echo "tag=$TAG" >> "$GITHUB_OUTPUT" + echo "version=${TAG#v}" >> "$GITHUB_OUTPUT" + + - name: Download release assets + env: + GH_TOKEN: ${{ github.token }} + TAG: ${{ steps.tag.outputs.tag }} + VERSION: ${{ steps.tag.outputs.version }} + run: | + gh release download "$TAG" \ + --repo crynta/terax-ai \ + --pattern "Terax_${VERSION}_amd64.deb" \ + --pattern "Terax_x64.app.tar.gz" \ + --pattern "Terax_aarch64.app.tar.gz" + + - name: Compute SRI hashes + id: hashes + env: + VERSION: ${{ steps.tag.outputs.version }} + run: | + hash_sri() { + openssl dgst -sha256 -binary "$1" | base64 | tr -d '\n' + } + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + echo "linux=sha256-$(hash_sri "Terax_${VERSION}_amd64.deb")" >> "$GITHUB_OUTPUT" + echo "x64-darwin=sha256-$(hash_sri "Terax_x64.app.tar.gz")" >> "$GITHUB_OUTPUT" + echo "aarch64-darwin=sha256-$(hash_sri "Terax_aarch64.app.tar.gz")" >> "$GITHUB_OUTPUT" + + - name: Update nix/sources.json + run: | + cat > nix/sources.json <<- EOF + { + "version": "${{ steps.hashes.outputs.version }}", + "hashes": { + "x86_64-linux": "${{ steps.hashes.outputs.linux }}", + "x86_64-darwin": "${{ steps.hashes.outputs.x64-darwin }}", + "aarch64-darwin": "${{ steps.hashes.outputs.aarch64-darwin }}" + } + } + EOF + + - name: Create PR + uses: peter-evans/create-pull-request@v8 + with: + commit-message: "update nix sources to ${{ steps.hashes.outputs.version }}" + title: "nix: update sources to ${{ steps.hashes.outputs.version }}" + body: 'Automated update of `nix/sources.json` for release ${{ steps.tag.outputs.tag }}.' + branch: update-nix-sources/${{ steps.hashes.outputs.version }} + delete-branch: true diff --git a/README.md b/README.md index d2774040..78f767ee 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ The default shell is detected in this order: `pwsh.exe` (PowerShell 7+) → `pow ## Linux notes - **Arch / AUR**: install via `yay -S terax-bin` (or `paru`, etc.). Tracks the latest release. +- **NixOS / Nix**: use the official flake — `nix profile install github:crynta/terax-ai` (non-NixOS), or import the flake and add `inputs.terax.packages.${pkgs.system}.terax` to `environment.systemPackages` (NixOS). The `nixosModules.terax` output is also available for a simpler setup. - **AppImage**: needs FUSE. Without it: `./Terax_*.AppImage --appimage-extract-and-run`. On Wayland with rendering glitches, try `WEBKIT_DISABLE_DMABUF_RENDERER=1`; otherwise use the `.deb` / `.rpm` which link against the system's GTK stack. ## Configure AI diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..08dc0f45 --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1778869304, + "narHash": "sha256-30sZNZoA1cqF5JNO9fVX+wgiQYjB7HJqqJ4ztCDeBZE=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "d233902339c02a9c334e7e593de68855ad26c4cb", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..1832be9f --- /dev/null +++ b/flake.nix @@ -0,0 +1,24 @@ +{ + description = "Terax - open-source lightweight cross-platform AI-native terminal (ADE)"; + + inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + + outputs = { self, nixpkgs }: let + forAllSystems = nixpkgs.lib.genAttrs [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]; + in { + packages = forAllSystems (system: let + pkgs = nixpkgs.legacyPackages.${system}; + in { + terax = pkgs.callPackage ./nix/package.nix { }; + default = self.packages.${system}.terax; + }); + + nixosModules.terax = { pkgs, ... }: { + environment.systemPackages = [ self.packages.${pkgs.system}.terax ]; + }; + + darwinModules.terax = { pkgs, ... }: { + environment.systemPackages = [ self.packages.${pkgs.system}.terax ]; + }; + }; +} diff --git a/nix/package.nix b/nix/package.nix new file mode 100644 index 00000000..7dd2db53 --- /dev/null +++ b/nix/package.nix @@ -0,0 +1,71 @@ +{ lib, stdenv, fetchurl +, dpkg, autoPatchelfHook, makeWrapper +, gtk3, gdk-pixbuf, cairo, glib, webkitgtk_4_1, libsoup_3, libgcc, gst_all_1 +}: + +let + sources = builtins.fromJSON (builtins.readFile ./sources.json); + version = sources.version; + + srcMap = { + x86_64-linux = fetchurl { + url = "https://github.com/crynta/terax-ai/releases/download/v${version}/Terax_${version}_amd64.deb"; + hash = sources.hashes.x86_64-linux; + }; + x86_64-darwin = fetchurl { + url = "https://github.com/crynta/terax-ai/releases/download/v${version}/Terax_x64.app.tar.gz"; + hash = sources.hashes.x86_64-darwin; + }; + aarch64-darwin = fetchurl { + url = "https://github.com/crynta/terax-ai/releases/download/v${version}/Terax_aarch64.app.tar.gz"; + hash = sources.hashes.aarch64-darwin; + }; + }; + + sys = stdenv.hostPlatform.system; +in + +assert lib.assertMsg (builtins.hasAttr sys srcMap) + "terax: unsupported platform ${sys}"; + +stdenv.mkDerivation { + pname = "terax"; + inherit version; + + src = srcMap.${sys}; + + nativeBuildInputs = lib.optionals stdenv.hostPlatform.isLinux [ + dpkg autoPatchelfHook makeWrapper + ]; + + buildInputs = lib.optionals stdenv.hostPlatform.isLinux [ + gtk3 gdk-pixbuf cairo glib webkitgtk_4_1 libsoup_3 libgcc + gst_all_1.gstreamer gst_all_1.gst-plugins-base + gst_all_1.gst-plugins-good gst_all_1.gst-plugins-bad + ]; + + GST_PLUGIN_SYSTEM_PATH = lib.optionalString stdenv.hostPlatform.isLinux + "${gst_all_1.gst-plugins-base}/lib/gstreamer-1.0:${gst_all_1.gst-plugins-good}/lib/gstreamer-1.0:${gst_all_1.gst-plugins-bad}/lib/gstreamer-1.0"; + + unpackPhase = if stdenv.hostPlatform.isLinux then "dpkg -x $src ." else "tar xzf $src"; + + installPhase = if stdenv.hostPlatform.isLinux then '' + mkdir -p $out/bin $out/share + cp -r usr/share/* $out/share/ + install -Dm755 usr/bin/terax $out/bin/terax + + wrapProgram $out/bin/terax \ + --prefix GST_PLUGIN_SYSTEM_PATH : "$GST_PLUGIN_SYSTEM_PATH" \ + --set XDG_DATA_DIRS "$GSETTINGS_SCHEMAS_PATH" + '' else '' + mkdir -p $out/Applications + cp -r *.app $out/Applications/ + ''; + + meta = with lib; { + description = "Open-source lightweight cross-platform AI-native terminal (ADE)"; + homepage = "https://terax.app"; + license = licenses.asl20; + platforms = [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" ]; + }; +} diff --git a/nix/sources.json b/nix/sources.json new file mode 100644 index 00000000..15269a51 --- /dev/null +++ b/nix/sources.json @@ -0,0 +1,8 @@ +{ + "version": "0.6.6", + "hashes": { + "x86_64-linux": "sha256-VBcgLoKSUy7QA8NyYkrfcCkldW3TSh1Pl0Ca3H7s7qY=", + "x86_64-darwin": "sha256-qIO23vLEotgMADxvrhGRePzsdkYZyoiAwFPeMuEFA8o=", + "aarch64-darwin": "sha256-2UenKa07wvumM+VY23sP7kdWEwd7UQ1dc1dXuylnJcg=" + } +}