🎉 Initial commit: PiAgentUI — AI Agent Desktop & Web UI
Build & Push Frontend Docker Image / build-and-push (push) Canceled after 0s
Build Validation / validate (push) Canceled after 6s
Build & Push Backend Docker Image / build-and-push (push) Failing after 10m10s
Build & Push Gateway Docker Image / build-and-push (push) Failing after 10m9s
Build & Push Frontend Docker Image / build-and-push (push) Canceled after 0s
Build Validation / validate (push) Canceled after 6s
Build & Push Backend Docker Image / build-and-push (push) Failing after 10m10s
Build & Push Gateway Docker Image / build-and-push (push) Failing after 10m9s
A professional workspace for AI coding agents with: - Real-time streaming chat with SSE - Session management (fork, clone, tree navigation) - MCP tools browser & metadata panel - Skills browser (global, project, package sources) - Voice input & STT provider configuration - Integrated terminal & file explorer - Model selector with capability metadata - Keyboard-first UI with command palette - 8 languages (en, pt-BR, es, ja, zh-CN, ar, bn, hi) - Tauri 2 desktop app - React 19 + TypeScript + Vite 8 + Tailwind CSS 4 - Pi Agent extension runtime Originally forked from OpenCodeUI, now an independent project. License: GPL-3.0-only
This commit is contained in:
commit
b3489e1ede
983 files changed
+158475
No files matched your search
@@ -0,0 +1,32 @@
|
||||
name: Build Validation
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: build-validation-${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Validate app
|
||||
run: npm run validate
|
||||
@@ -0,0 +1,46 @@
|
||||
name: Deploy to GitHub Pages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [dev]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
concurrency:
|
||||
group: pages
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
|
||||
- run: npm ci
|
||||
|
||||
- run: npm run build
|
||||
env:
|
||||
VITE_BASE_PATH: /OpenCodeUI/
|
||||
|
||||
- uses: actions/upload-pages-artifact@v5
|
||||
with:
|
||||
path: dist
|
||||
|
||||
deploy:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
steps:
|
||||
- id: deployment
|
||||
uses: actions/deploy-pages@v5
|
||||
@@ -0,0 +1,66 @@
|
||||
name: Build & Push Backend Docker Image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'docker/Dockerfile.backend'
|
||||
- 'docker/backend-entrypoint.sh'
|
||||
schedule:
|
||||
# 每天自动重建,跟进 opencode 最新版本
|
||||
- cron: '0 4 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: docker-backend-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository_owner }}/opencodeui-backend
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 120
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
type=sha,prefix=
|
||||
type=ref,event=branch
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: docker/Dockerfile.backend
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
@@ -0,0 +1,71 @@
|
||||
name: Build & Push Frontend Docker Image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'src/**'
|
||||
- 'public/**'
|
||||
- 'index.html'
|
||||
- 'package.json'
|
||||
- 'package-lock.json'
|
||||
- 'vite.config.ts'
|
||||
- 'tsconfig*.json'
|
||||
- 'docker/Dockerfile.frontend'
|
||||
- 'docker/Caddyfile'
|
||||
- 'docker/Caddyfile.standalone'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: docker-frontend-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository_owner }}/opencodeui-frontend
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
type=sha,prefix=
|
||||
type=ref,event=branch
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: docker/Dockerfile.frontend
|
||||
build-args: |
|
||||
NPM_REGISTRY=https://registry.npmjs.org/
|
||||
NPM_REGISTRY_FALLBACK=https://registry.npmmirror.com/
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
@@ -0,0 +1,65 @@
|
||||
name: Build & Push Gateway Docker Image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'docker/Dockerfile.gateway'
|
||||
- 'docker/Caddyfile.gateway'
|
||||
- 'docker/entrypoint-gateway.sh'
|
||||
- 'src-router/**'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: docker-gateway-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository_owner }}/opencodeui-gateway
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
type=sha,prefix=
|
||||
type=ref,event=branch
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: docker/Dockerfile.gateway
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
@@ -0,0 +1,240 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
concurrency:
|
||||
group: release-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
# ============================================
|
||||
# Desktop builds (Windows, macOS, Linux)
|
||||
# ============================================
|
||||
build-desktop:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: macos-latest
|
||||
args: '--target aarch64-apple-darwin'
|
||||
arch: aarch64
|
||||
os: macos
|
||||
- platform: macos-latest
|
||||
args: '--target x86_64-apple-darwin'
|
||||
arch: x86_64
|
||||
os: macos
|
||||
- platform: ubuntu-22.04
|
||||
args: ''
|
||||
arch: x86_64
|
||||
os: linux
|
||||
- platform: windows-latest
|
||||
args: ''
|
||||
arch: x86_64
|
||||
os: windows
|
||||
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: lts/*
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
|
||||
|
||||
- name: Rust cache
|
||||
uses: swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: './src-tauri -> target'
|
||||
key: ${{ matrix.os }}-${{ matrix.arch }}
|
||||
|
||||
- name: Install Linux dependencies
|
||||
if: matrix.platform == 'ubuntu-22.04'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
|
||||
|
||||
- run: npm ci
|
||||
|
||||
# tauri-action 自动执行 beforeBuildCommand (npm run build) + cargo build
|
||||
- name: Build desktop app
|
||||
uses: tauri-apps/tauri-action@v0
|
||||
with:
|
||||
args: ${{ matrix.args }}
|
||||
|
||||
- name: Prepare artifacts
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p release-artifacts
|
||||
BUNDLE_DIR="src-tauri/target/release/bundle"
|
||||
if [[ "${{ matrix.os }}" == "macos" ]]; then
|
||||
BUNDLE_DIR="src-tauri/target/${{ matrix.arch }}-apple-darwin/release/bundle"
|
||||
fi
|
||||
|
||||
if [[ "${{ matrix.os }}" == "windows" ]]; then
|
||||
find "$BUNDLE_DIR/nsis" -name "*.exe" -exec cp {} release-artifacts/ \; 2>/dev/null || true
|
||||
elif [[ "${{ matrix.os }}" == "macos" ]]; then
|
||||
find "$BUNDLE_DIR/dmg" -name "*.dmg" -exec cp {} release-artifacts/ \; 2>/dev/null || true
|
||||
elif [[ "${{ matrix.os }}" == "linux" ]]; then
|
||||
find "$BUNDLE_DIR/deb" -name "*.deb" -exec cp {} release-artifacts/ \; 2>/dev/null || true
|
||||
find "$BUNDLE_DIR/appimage" -name "*.AppImage" -exec cp {} release-artifacts/ \; 2>/dev/null || true
|
||||
fi
|
||||
|
||||
echo "Artifacts:"
|
||||
ls -R release-artifacts
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: artifacts-desktop-${{ matrix.os }}-${{ matrix.arch }}
|
||||
path: release-artifacts
|
||||
if-no-files-found: warn
|
||||
retention-days: 1
|
||||
|
||||
# ============================================
|
||||
# Android builds (arm64 + armv7 并行)
|
||||
# ============================================
|
||||
build-android:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- target: aarch64
|
||||
rust_target: aarch64-linux-android
|
||||
label: arm64
|
||||
- target: armv7
|
||||
rust_target: armv7-linux-androideabi
|
||||
label: armv7
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: lts/*
|
||||
cache: 'npm'
|
||||
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
|
||||
- uses: android-actions/setup-android@v3
|
||||
|
||||
- run: sdkmanager "ndk;29.0.14206865"
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.rust_target }}
|
||||
|
||||
- name: Rust cache
|
||||
uses: swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: './src-tauri -> target'
|
||||
key: android-${{ matrix.target }}
|
||||
|
||||
- name: Gradle cache
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
src-tauri/gen/android/.gradle
|
||||
key: gradle-${{ matrix.target }}-${{ hashFiles('src-tauri/gen/android/**/*.gradle*', 'src-tauri/gen/android/**/gradle-wrapper.properties') }}
|
||||
restore-keys: gradle-
|
||||
|
||||
- run: npm ci
|
||||
|
||||
- name: Setup Android signing
|
||||
run: |
|
||||
cd src-tauri/gen/android
|
||||
echo "keyAlias=${{ secrets.ANDROID_KEY_ALIAS }}" > keystore.properties
|
||||
echo "password=${{ secrets.ANDROID_KEY_PASSWORD }}" >> keystore.properties
|
||||
base64 -d <<< "${{ secrets.ANDROID_KEY_BASE64 }}" > $RUNNER_TEMP/keystore.jks
|
||||
echo "storeFile=$RUNNER_TEMP/keystore.jks" >> keystore.properties
|
||||
|
||||
- name: Build and sign APK
|
||||
run: |
|
||||
VERSION=${{ github.ref_name }}
|
||||
BT="$ANDROID_HOME/build-tools/$(ls $ANDROID_HOME/build-tools/ | tail -1)"
|
||||
|
||||
npx tauri android build --apk --target ${{ matrix.target }}
|
||||
|
||||
SIGNED_APK=$(find src-tauri/gen/android/app/build/outputs/apk -path '*/release/*-signed*' -name '*.apk' -type f 2>/dev/null | head -1)
|
||||
RELEASE_APK=$(find src-tauri/gen/android/app/build/outputs/apk -path '*/release/*.apk' -name '*.apk' -type f 2>/dev/null | head -1)
|
||||
APK_PATH="${SIGNED_APK:-$RELEASE_APK}"
|
||||
DEST="OpenCodeUI-${VERSION}-android-${{ matrix.label }}.apk"
|
||||
|
||||
if $BT/apksigner verify "$APK_PATH" 2>/dev/null; then
|
||||
cp "$APK_PATH" "$DEST"
|
||||
else
|
||||
$BT/zipalign -v 4 "$APK_PATH" "${APK_PATH}.aligned"
|
||||
$BT/apksigner sign \
|
||||
--ks $RUNNER_TEMP/keystore.jks \
|
||||
--ks-key-alias ${{ secrets.ANDROID_KEY_ALIAS }} \
|
||||
--ks-pass pass:${{ secrets.ANDROID_KEY_PASSWORD }} \
|
||||
--key-pass pass:${{ secrets.ANDROID_KEY_PASSWORD }} \
|
||||
--out "$DEST" "${APK_PATH}.aligned"
|
||||
fi
|
||||
|
||||
mkdir -p release-artifacts
|
||||
mv "$DEST" release-artifacts/
|
||||
env:
|
||||
NDK_HOME: ${{ env.ANDROID_HOME }}/ndk/29.0.14206865
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: artifacts-android-${{ matrix.label }}
|
||||
path: release-artifacts/*
|
||||
retention-days: 1
|
||||
|
||||
# ============================================
|
||||
# Publish Release
|
||||
# ============================================
|
||||
publish-release:
|
||||
permissions:
|
||||
contents: write
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-desktop, build-android]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
path: artifacts
|
||||
pattern: artifacts-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Display artifacts
|
||||
run: ls -R artifacts
|
||||
|
||||
- name: Extract changelog
|
||||
id: changelog
|
||||
run: |
|
||||
TAG="${{ github.ref_name }}"
|
||||
BODY=$(sed -n "/^## \[${TAG}\]/,/^## \[/{ /^## \[${TAG}\]/d; /^## \[/d; p; }" CHANGELOG.md)
|
||||
BODY=$(echo "$BODY" | sed -e '/./,$!d' -e :a -e '/^\n*$/{$d;N;ba;}')
|
||||
if [ -z "$BODY" ]; then
|
||||
BODY="No changelog entry found for ${TAG}."
|
||||
fi
|
||||
echo "$BODY" > /tmp/release-body.md
|
||||
printf '\n---\n\n**Desktop:** Windows (.exe), macOS (.dmg), Linux (.deb, .AppImage)\n**Mobile:** Android (.apk) — arm64, armeabi-v7a\n' >> /tmp/release-body.md
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: ${{ github.ref_name }}
|
||||
name: 'OpenCodeUI ${{ github.ref_name }}'
|
||||
body_path: /tmp/release-body.md
|
||||
files: artifacts/*
|
||||
draft: false
|
||||
prerelease: ${{ contains(github.ref_name, 'canary') || contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
Reference in new issue
Block a user