From 7144d7d703e1a7fb58f1a6d67f55afa52910338c Mon Sep 17 00:00:00 2001 From: Afanasy Volkov Date: Sun, 4 Oct 2026 15:21:02 +0000 Subject: [PATCH] feat(multica): publish fork Multica CLI installers (agent-arka support) - multica/install.sh (Linux/macOS/WSL): downloads the fork-built multica CLI (0.6.1-arka, agent-arka runtime support) from arka/public releases, verifies SHA256, installs to /usr/local/bin or ~/.local/bin, PATH. - multica/install.ps1 (Windows): same, installs to ~/.multica/bin. - multica/README.md + root README table entry. - Release multica-v0.6.1-arka hosts multica-cli-* tarballs/zip + checksums. --- README.md | 15 ++++ multica/README.md | 59 +++++++++++++++ multica/install.ps1 | 133 +++++++++++++++++++++++++++++++++ multica/install.sh | 175 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 382 insertions(+) create mode 100644 multica/README.md create mode 100644 multica/install.ps1 create mode 100644 multica/install.sh diff --git a/README.md b/README.md index bcbce0a..b7eebaf 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ |-------|-----| | [`agent-arka/`](agent-arka/) | Agent Arka: демон + **веб-дашборд** (`http://127.0.0.1:4545`), установщик и пакеты | | [`opencode/`](opencode/) | Провайдер OpenCode **Arka-AI**: установщик, плагин, skill, каталог чат-моделей | +| [`multica/`](multica/) | **Multica fork CLI**: daemon c поддержкой agent-arka, установщик | Agent Arka (веб-интерфейс), Linux / WSL: @@ -35,3 +36,17 @@ irm https://git.arka-ai.ru/arka/public/raw/branch/main/opencode/install-arka-pro ``` Подробности: [opencode/README.md](opencode/README.md) — Windows, Desktop, установка из чата OpenCode. + +Multica fork CLI, macOS / Linux / WSL: + +```bash +curl -fsSL https://git.arka-ai.ru/arka/public/raw/branch/main/multica/install.sh | bash +``` + +Multica fork CLI, Windows (PowerShell): + +```powershell +irm https://git.arka-ai.ru/arka/public/raw/branch/main/multica/install.ps1 | iex +``` + +Подробности: [multica/README.md](multica/README.md). diff --git a/multica/README.md b/multica/README.md new file mode 100644 index 0000000..87046c8 --- /dev/null +++ b/multica/README.md @@ -0,0 +1,59 @@ +# Multica fork CLI (Arka) + +Кастомный билд CLI Multica от Arka: поддержка **agent-arka** runtime (провайдер +`agent-arka` на `plan.arka-ai.ru`), Arka SSO, русская локализация. Скачивается +из публичных релизов этого репозитория; токен не нужен. + +## Установка + +macOS / Linux / WSL: + +```bash +curl -fsSL https://git.arka-ai.ru/arka/public/raw/branch/main/multica/install.sh | bash +``` + +Windows (PowerShell): + +```powershell +irm https://git.arka-ai.ru/arka/public/raw/branch/main/multica/install.ps1 | iex +``` + +Бинарь ставится в `/usr/local/bin` (или `~/.local/bin`), на Windows — в +`~\.multica\bin`, и добавляется в `PATH`. + +## Подключение к серверу + +```bash +multica setup self-host \ + --server-url https://plan.arka-ai.ru \ + --app-url https://plan.arka-ai.ru +``` + +Команда настроит CLI, откроет браузер для входа и запустит daemon. + +## Проверка + +```bash +multica version # 0.6.1-arka +multica daemon status # running; агенты включают agent-arka +``` + +Проверить, что бинарь умеет agent-arka: + +```bash +multica daemon probe-runtimes +# provider_summary должен содержать "agent-arka" +``` + +## Пин версии + +```bash +MULTICA_VERSION=0.6.1-arka curl -fsSL .../multica/install.sh | bash +``` + +## Релизы + +Бинари публикуются в [релизах](https://git.arka-ai.ru/arka/public/releases/tag/multica-v0.6.1-arka): +`multica-cli--linux-{amd64,arm64}.tar.gz`, +`multica-cli--darwin-{amd64,arm64}.tar.gz`, +`multica-cli--windows-amd64.zip`, `checksums.txt`. diff --git a/multica/install.ps1 b/multica/install.ps1 new file mode 100644 index 0000000..9215d39 --- /dev/null +++ b/multica/install.ps1 @@ -0,0 +1,133 @@ +# Multica fork CLI — Windows installer +# +# Installs the fork-built `multica.exe` CLI (with agent-arka runtime support, +# Arka SSO, Russian i18n) from arka/public releases. +# +# irm https://git.arka-ai.ru/arka/public/raw/branch/main/multica/install.ps1 | iex +# +# Environment: +# $env:MULTICA_VERSION pin a release (e.g. 0.6.1-arka). Default: newest multica-v* on git.arka-ai.ru/arka/public + +$ErrorActionPreference = "Stop" + +$PublicApi = if ($env:MULTICA_PUBLIC_API) { $env:MULTICA_PUBLIC_API } else { "https://git.arka-ai.ru/api/v1" } +$PublicDl = if ($env:MULTICA_PUBLIC_DL) { $env:MULTICA_PUBLIC_DL } else { "https://git.arka-ai.ru/arka/public/releases/download" } +$Repo = "arka/public" +$TagPrefix = "multica-v" + +$BinDir = Join-Path $env:USERPROFILE ".multica\bin" + +function Write-Info { Write-Host "==> $args" -ForegroundColor Cyan } +function Write-Ok { Write-Host "OK $args" -ForegroundColor Green } +function Write-Warn { Write-Host "WARN $args" -ForegroundColor Yellow } +function Write-Fail { Write-Host "FAIL $args" -ForegroundColor Red; exit 1 } + +function Get-WindowsCliArch { + $arch = $env:PROCESSOR_ARCHITECTURE + if ($arch -eq "AMD64" -or $arch -eq "x86_64") { return "amd64" } + if ($arch -eq "ARM64") { return "arm64" } + Write-Fail "Unsupported architecture: $arch" +} + +function Get-LatestMulticaVersion { + $url = "$PublicApi/repos/$Repo/releases?limit=50" + try { + $releases = Invoke-RestMethod -Uri $url -UseBasicParsing -ErrorAction Stop + } catch { + Write-Fail "Cannot list releases at $url : $_" + } + $tags = $releases | Where-Object { $_.tag_name -like "$TagPrefix*" } | ForEach-Object { $_.tag_name } + if (-not $tags) { Write-Fail "No ${TagPrefix}* releases on $Repo yet" } + $latest = $tags | Sort-Object -Descending | Select-Object -First 1 + return $latest.Substring($TagPrefix.Length) +} + +function Add-ToUserPath { + param([string]$Dir) + $currentPath = [Environment]::GetEnvironmentVariable("Path", "User") + if ($currentPath -and $currentPath.Split(";") -contains $Dir) { return } + $newPath = if ($currentPath) { "$currentPath;$Dir" } else { $Dir } + [Environment]::SetEnvironmentVariable("Path", $newPath, "User") + if ($env:Path -notlike "*$Dir*") { + $env:Path = "$Dir;$env:Path" + } + Write-Ok "Added $Dir to user PATH" +} + +if (-not [Environment]::Is64BitOperatingSystem) { + Write-Fail "Multica requires a 64-bit Windows installation." +} + +$arch = Get-WindowsCliArch + +$version = if ($env:MULTICA_VERSION) { $env:MULTICA_VERSION.TrimStart("v").TrimStart($TagPrefix) } else { Get-LatestMulticaVersion } +Write-Info "Installing Multica fork CLI ${version} (windows-$arch)..." + +$asset = "multica-cli-$version-windows-$arch.zip" +$url = "$PublicDl/$TagPrefix$version/$asset" +$tmpDir = Join-Path ([System.IO.Path]::GetTempPath()) "multica-install" + +if (Test-Path $tmpDir) { Remove-Item $tmpDir -Recurse -Force } +New-Item -ItemType Directory -Path $tmpDir | Out-Null + +Write-Info "Downloading $url ..." +try { + Invoke-WebRequest -Uri $url -OutFile (Join-Path $tmpDir "multica.zip") -UseBasicParsing +} catch { + Remove-Item $tmpDir -Recurse -Force + Write-Fail "Failed to download CLI binary: $_" +} + +# Verify SHA256 checksum +$checksumUrl = "$PublicDl/$TagPrefix$version/checksums.txt" +try { + $checksums = Invoke-WebRequest -Uri $checksumUrl -UseBasicParsing -ErrorAction Stop + $checksumContent = if ($checksums.Content -is [byte[]]) { + [System.Text.Encoding]::UTF8.GetString($checksums.Content) + } else { + [string]$checksums.Content + } + $zipFile = Join-Path $tmpDir "multica.zip" + $actualHash = (Get-FileHash -Path $zipFile -Algorithm SHA256).Hash.ToLower() + $expectedLine = ($checksumContent -split "`r?`n") | Where-Object { $_ -match [regex]::Escape($asset) } | Select-Object -First 1 + if ($expectedLine) { + $expectedHash = ($expectedLine -split "\s+")[0].ToLower() + if ($actualHash -ne $expectedHash) { + Remove-Item $tmpDir -Recurse -Force + Write-Fail "Checksum verification failed. Expected: $expectedHash, Got: $actualHash" + } + Write-Ok "Checksum verified" + } else { + Write-Warn "Could not find checksum entry for $asset - skipping verification." + } +} catch { + Write-Warn "Could not download checksums.txt - skipping verification." +} + +Expand-Archive -Path (Join-Path $tmpDir "multica.zip") -DestinationPath $tmpDir -Force + +if (-not (Test-Path $BinDir)) { + New-Item -ItemType Directory -Path $BinDir -Force | Out-Null +} + +$exeSrc = Join-Path $tmpDir "multica.exe" +if (-not (Test-Path $exeSrc)) { + $exeSrc = Get-ChildItem -Path $tmpDir -Filter "multica.exe" -Recurse | Select-Object -First 1 -ExpandProperty FullName +} +if (-not $exeSrc -or -not (Test-Path $exeSrc)) { + Remove-Item $tmpDir -Recurse -Force + Write-Fail "multica.exe not found in downloaded archive." +} + +Copy-Item $exeSrc (Join-Path $BinDir "multica.exe") -Force +Remove-Item $tmpDir -Recurse -Force + +Add-ToUserPath $BinDir +Write-Ok "Multica CLI installed to $BinDir\multica.exe" + +Write-Host "" +Write-Host " Next — connect to your Multica server:" +Write-Host " multica setup self-host" +Write-Host " Or for this instance:" +Write-Host " multica setup self-host --server-url https://plan.arka-ai.ru --app-url https://plan.arka-ai.ru" +Write-Host "" diff --git a/multica/install.sh b/multica/install.sh new file mode 100644 index 0000000..54b8e55 --- /dev/null +++ b/multica/install.sh @@ -0,0 +1,175 @@ +#!/usr/bin/env bash +# Multica fork CLI — installer (Linux / macOS / WSL). +# +# Installs the fork-built `multica` CLI (with agent-arka runtime support, Arka +# SSO, Russian i18n) from arka/public releases. +# +# curl -fsSL https://git.arka-ai.ru/arka/public/raw/branch/main/multica/install.sh | bash +# +# Environment: +# MULTICA_VERSION pin a release (e.g. 0.6.1-arka). Default: newest multica-v* on git.arka-ai.ru/arka/public +# MULTICA_BIN_DIR install dir (default: /usr/local/bin, else ~/.local/bin) +# NO_COLOR 1 to disable color output + +if [ -z "${BASH_VERSION:-}" ]; then + echo "The Multica installer needs bash. Run:" >&2 + echo " curl -fsSL https://git.arka-ai.ru/arka/public/raw/branch/main/multica/install.sh | bash" >&2 + exit 1 +fi + +set -euo pipefail + +PUBLIC_API="${MULTICA_PUBLIC_API:-https://git.arka-ai.ru/api/v1}" +PUBLIC_DL="${MULTICA_PUBLIC_DL:-https://git.arka-ai.ru/arka/public/releases/download}" +REPO="arka/public" +TAG_PREFIX="multica-v" + +if [[ -t 1 && -z "${NO_COLOR:-}" ]]; then + C_GREEN=$'\033[32m'; C_YELLOW=$'\033[33m'; C_RED=$'\033[31m'; C_BOLD=$'\033[1m'; C_RESET=$'\033[0m' +else + C_GREEN=''; C_YELLOW=''; C_RED=''; C_BOLD=''; C_RESET='' +fi + +info() { printf '%s\n' "$*"; } +ok() { printf '%s✓%s %s\n' "$C_GREEN" "$C_RESET" "$*"; } +warn() { printf '%s⚠%s %s\n' "$C_YELLOW" "$C_RESET" "$*"; } +die() { printf '%s✗%s %s\n' "$C_RED" "$C_RESET" "$*" >&2; exit 1; } + +_mc_tmp="" +cleanup() { [[ -n "${_mc_tmp:-}" ]] && rm -rf "$_mc_tmp"; } +trap cleanup EXIT + +detect_platform() { + local os arch + os=$(uname -s | tr '[:upper:]' '[:lower:]') + arch=$(uname -m) + case "$arch" in + x86_64|amd64) arch="amd64" ;; + aarch64|arm64) arch="arm64" ;; + *) die "Unsupported architecture: $arch" ;; + esac + case "$os" in + linux) PLATFORM="linux-${arch}" ;; + darwin) PLATFORM="darwin-${arch}" ;; + mingw*|msys*|cygwin*) + die "This curl installer is for Linux/macOS/WSL. On Windows run the PowerShell installer instead:"$'\n'" irm https://git.arka-ai.ru/arka/public/raw/branch/main/multica/install.ps1 | iex" + ;; + *) die "Unsupported OS: $os" ;; + esac +} + +fetch_latest_version() { + local json tags + json=$(curl -fsSL "${PUBLIC_API}/repos/${REPO}/releases?limit=50") || die "Cannot list releases at ${PUBLIC_API}/repos/${REPO}/releases" + tags=$(printf '%s' "$json" | grep -oE '"tag_name":[[:space:]]*"'"${TAG_PREFIX}"'[^"]+"' | sed 's/.*"'"${TAG_PREFIX}"'//;s/"$//' || true) + if [[ -z "$tags" ]]; then + die "No ${TAG_PREFIX}* releases on ${REPO} yet" + fi + printf '%s\n' "$tags" | head -n 1 +} + +sha256_file() { + if command -v sha256sum >/dev/null 2>&1; then + sha256sum "$1" | awk '{print $1}' + elif command -v shasum >/dev/null 2>&1; then + shasum -a 256 "$1" | awk '{print $1}' + else + die "Need sha256sum or shasum" + fi +} + +ensure_path() { + local bindir="$1" + case ":$PATH:" in + *":${bindir}:"*) return 0 ;; + esac + local line="export PATH=\"${bindir}:\$PATH\"" + local rc + for rc in "${HOME}/.zprofile" "${HOME}/.zshrc" "${HOME}/.bash_profile" "${HOME}/.bashrc" "${HOME}/.profile"; do + [[ -f "$rc" ]] || continue + if grep -Fqs "$bindir" "$rc"; then + return 0 + fi + done + if [[ -n "${SHELL:-}" && "${SHELL}" == *zsh* ]]; then + rc="${HOME}/.zshrc" + else + rc="${HOME}/.bashrc" + [[ -f "$rc" ]] || rc="${HOME}/.profile" + fi + printf '\n# Multica CLI\n%s\n' "$line" >>"$rc" + warn "Added ${bindir} to PATH in ${rc} (open a new shell, or: source ${rc})" +} + +main() { + printf '%s\n' "${C_BOLD}Multica${C_RESET} — fork CLI installer (agent-arka support)" + command -v curl >/dev/null 2>&1 || die "curl is required" + command -v tar >/dev/null 2>&1 || die "tar is required" + + detect_platform + + local version + if [[ -n "${MULTICA_VERSION:-}" ]]; then + version="${MULTICA_VERSION#v}" + version="${version#multica-v}" + info "Using pinned version ${version}" + else + info "Resolving latest Multica release…" + version=$(fetch_latest_version) + info "Latest: ${version}" + fi + + local asset="multica-cli-${version}-${PLATFORM}.tar.gz" + local url="${PUBLIC_DL}/${TAG_PREFIX}${version}/${asset}" + + _mc_tmp=$(mktemp -d) + info "Downloading ${url} ..." + curl -fsSL "$url" -o "$_mc_tmp/multica.tar.gz" || die "Failed to download ${asset}" + + info "Verifying checksum …" + local expected actual + expected=$(curl -fsSL "${PUBLIC_DL}/${TAG_PREFIX}${version}/checksums.txt" | awk -v a="$asset" '$2==a {print $1; exit}' 2>/dev/null || true) + actual=$(sha256_file "$_mc_tmp/multica.tar.gz") + if [[ -n "$expected" ]]; then + if [[ "$expected" != "$actual" ]]; then + die "Checksum mismatch for ${asset}: expected ${expected}, got ${actual}" + fi + ok "Checksum verified" + else + warn "No checksum entry for ${asset}; skipping verification" + fi + + tar -xzf "$_mc_tmp/multica.tar.gz" -C "$_mc_tmp" multica || die "Failed to extract multica" + + local bindir + if [[ -n "${MULTICA_BIN_DIR:-}" ]]; then + bindir="${MULTICA_BIN_DIR}" + elif [[ -w /usr/local/bin ]]; then + bindir="/usr/local/bin" + elif command -v sudo >/dev/null 2>&1; then + bindir="/usr/local/bin" + else + bindir="${HOME}/.local/bin" + fi + mkdir -p "$bindir" + + if [[ ! -w "$bindir" ]]; then + sudo mv "$_mc_tmp/multica" "$bindir/multica" || die "Cannot write to ${bindir}" + else + mv "$_mc_tmp/multica" "$bindir/multica" + fi + chmod +x "$bindir/multica" + ensure_path "$bindir" + + ok "Multica CLI ${version} installed to ${bindir}/multica" + rm -rf "$_mc_tmp"; _mc_tmp="" + + printf '\n' + printf ' Next — connect to your Multica server:\n' + printf ' multica setup self-host\n' + printf ' Or for this instance:\n' + printf ' multica setup self-host --server-url https://plan.arka-ai.ru --app-url https://plan.arka-ai.ru\n' + printf '\n' +} + +main "$@"