Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
410 changes: 0 additions & 410 deletions .claude/skills/gaia-release/SKILL.md

This file was deleted.

5 changes: 0 additions & 5 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,6 @@ electron:
- changed-files:
- any-glob-to-any-file: ['src/gaia/apps/**/*.html', 'src/gaia/apps/**/*.js', 'src/gaia/apps/**/*.css']

# Website changes (Astro + Tailwind landing site)
website:
- changed-files:
- any-glob-to-any-file: ['website/**/*']

# Dependencies
dependencies:
- changed-files:
Expand Down
124 changes: 3 additions & 121 deletions .github/workflows/build-installers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,6 @@ on:
- 'src/gaia/apps/webui/main.cjs'
- 'src/gaia/apps/webui/bin/**'
- 'src/gaia/apps/webui/services/**'
# Cover the installer-smoke test tree (issue #941) so a PR that
# only touches the smoke-test layer still triggers structural smoke.
# Narrower than `tests/electron/**` so Jest-only edits to e.g.
# test_electron_chat_app.js don't re-run the multi-platform build.
- 'tests/electron/_helpers/**'
- 'tests/electron/*-smoke.test.mjs'
- 'tests/electron/fixtures/**'
- 'src/gaia/version.py'

Expand Down Expand Up @@ -235,75 +229,6 @@ jobs:
chmod 0755 "${DEST_DIR}/uv"
"${DEST_DIR}/uv" --version

- name: Fetch uv binary (Windows)
if: matrix.platform == 'windows'
shell: bash
run: |
set -euo pipefail
UV_VERSION="0.5.14"
UV_ZIP="uv-x86_64-pc-windows-msvc.zip"
UV_URL="https://github.com/astral-sh/uv/releases/download/${UV_VERSION}/${UV_ZIP}"
# This must be set to the official tarball SHA256 (archive digest).
# DO NOT merge this PR without replacing the placeholder below
# with the real value — the build intentionally fails if the
# checksum is not provided so we never ship an unverified uv.
UV_TARBALL_SHA256="ee2468e40320a0a2a36435e66bbd0d861228c4c06767f22d97876528138f4ba0"

DEST_DIR="src/gaia/apps/webui/build/vendor/uv/win-x64"
mkdir -p "${DEST_DIR}"
tmpdir="$(mktemp -d)"
echo "Downloading ${UV_URL}"
curl -fsSL --retry 3 --retry-delay 5 -o "${tmpdir}/${UV_ZIP}" "${UV_URL}"

if [ -z "${UV_TARBALL_SHA256}" ] || [ "${UV_TARBALL_SHA256}" = "REPLACE_ME_WIN_UV_TARBALL_SHA256" ]; then
echo "ERROR: UV_TARBALL_SHA256 is not set in the workflow. Set it to the upstream tarball SHA256 to proceed." >&2
exit 1
fi

echo "${UV_TARBALL_SHA256} ${tmpdir}/${UV_ZIP}" | sha256sum -c -

unzip -q "${tmpdir}/${UV_ZIP}" -d "${tmpdir}"
# Copy uv.exe from extracted tree — fail if not found.
FOUND=$(find "${tmpdir}" -type f -iname uv.exe | head -n1 || true)
if [ -z "${FOUND}" ]; then
echo "ERROR: uv.exe not found in the downloaded archive" >&2
exit 1
fi
cp "${FOUND}" "${DEST_DIR}/uv.exe"
chmod 0755 "${DEST_DIR}/uv.exe"
"${DEST_DIR}/uv.exe" --version || true

# Compute SHA256 of the extracted binary and inject into source
BIN_SHA=$(sha256sum "${DEST_DIR}/uv.exe" | cut -d' ' -f1)
echo "Computed uv.exe SHA256: ${BIN_SHA}"
# Replace placeholder in backend-installer.cjs so runtime can verify
sed -i "s/<WIN_UV_EXTRACTED_SHA256_PLACEHOLDER>/${BIN_SHA}/g" src/gaia/apps/webui/services/backend-installer.cjs

- name: Fetch uv binary (macOS)
if: matrix.platform == 'macos'
shell: bash
run: |
set -euo pipefail
UV_VERSION="0.5.14"
UV_TARBALL="uv-aarch64-apple-darwin.tar.gz"
# Upstream tarball SHA256 (archive digest)
UV_SHA256="d548dffc256014c4c8c693e148140a3a21bcc2bf066a35e1d5f0d24c91d32112"
UV_URL="https://github.com/astral-sh/uv/releases/download/${UV_VERSION}/${UV_TARBALL}"
DEST_DIR="src/gaia/apps/webui/build/vendor/uv/mac-arm64"
mkdir -p "${DEST_DIR}"
tmpdir="$(mktemp -d)"
echo "Downloading ${UV_URL}"
curl -fsSL --retry 3 --retry-delay 5 -o "${tmpdir}/${UV_TARBALL}" "${UV_URL}"
echo "${UV_SHA256} ${tmpdir}/${UV_TARBALL}" | shasum -a 256 -c -
tar -xzf "${tmpdir}/${UV_TARBALL}" -C "${tmpdir}"
cp "${tmpdir}/uv-aarch64-apple-darwin/uv" "${DEST_DIR}/uv"
chmod 0755 "${DEST_DIR}/uv"
"${DEST_DIR}/uv" --version
# Echo the extracted-binary SHA (pre-codesign). To bump the
# runtime's POST-codesign digest (BUNDLED_UV_SHA256[mac-arm64]),
# run CI and copy the value from the dmg-structural-smoke output.
shasum -a 256 "${DEST_DIR}/uv"

- name: Build frontend (Vite)
working-directory: src/gaia/apps/webui
shell: bash
Expand Down Expand Up @@ -607,46 +532,6 @@ jobs:
GAIA_APPIMAGE: ${{ steps.locate.outputs.appimage }}
run: node --test tests/electron/appimage-smoke.test.mjs

# ─── DMG structural smoke (issue #941) ──────────────────────────────
# Mirrors appimage-structural-smoke for the macOS DMG. Catches the
# failure mode that bit v0.17.5: a darwin-arm64 install that hard-fails
# in ensure-uv on first launch because the bundled uv either was never
# shipped or has the wrong SHA256 against BUNDLED_UV_SHA256[mac-arm64]
# in backend-installer.cjs.
#
# MUST be present in build-complete `needs:` below — without that
# wiring, a failing DMG smoke does not block release-readiness.
dmg-structural-smoke:
name: DMG structural smoke
needs: build
if: always() && needs.build.result == 'success'
runs-on: macos-latest # Apple Silicon (arm64) — matches build matrix
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Download macOS installer artifact
uses: actions/download-artifact@v6
with:
name: macos-installer # ${{ matrix.platform }}-installer with platform=macos
path: ${{ runner.temp }}/macos-installer

- name: Locate DMG
id: locate
shell: bash
run: |
set -euo pipefail
DMG=$(ls "${RUNNER_TEMP}/macos-installer"/*.dmg | head -n1)
echo "Found DMG: ${DMG}"
echo "dmg=${DMG}" >> "$GITHUB_OUTPUT"

- name: Structural smoke (uv binary, mode, sha256, --version)
env:
GAIA_DMG: ${{ steps.locate.outputs.dmg }}
run: node --test tests/electron/dmg-smoke.test.mjs

appimage-distro-matrix:
name: AppImage distro matrix
needs: build
Expand Down Expand Up @@ -1086,7 +971,6 @@ jobs:
- appimage-structural-smoke
- appimage-distro-matrix
- appimage-userns-restricted
- dmg-structural-smoke
if: always()
steps:
- name: Verify all platform builds and smoke tests succeeded
Expand All @@ -1096,24 +980,22 @@ jobs:
structural_result="${{ needs.appimage-structural-smoke.result }}"
distro_result="${{ needs.appimage-distro-matrix.result }}"
userns_result="${{ needs.appimage-userns-restricted.result }}"
dmg_result="${{ needs.dmg-structural-smoke.result }}"
echo "build: $build_result"
echo "appimage-structural-smoke: $structural_result"
echo "appimage-distro-matrix: $distro_result"
echo "appimage-userns-restricted: $userns_result"
echo "dmg-structural-smoke: $dmg_result"
fail=0
if [ "$build_result" != "success" ]; then
echo "::error::One or more platform installer builds failed"
fail=1
fi
for r in "$structural_result" "$distro_result" "$userns_result" "$dmg_result"; do
for r in "$structural_result" "$distro_result" "$userns_result"; do
if [ "$r" != "success" ] && [ "$r" != "skipped" ]; then
echo "::error::Installer smoke job failed (status: $r)"
echo "::error::AppImage smoke job failed (status: $r)"
fail=1
fi
done
if [ "$fail" -eq 1 ]; then
exit 1
fi
echo "All platform installers built and installer smoke suite passed."
echo "All platform installers built and AppImage smoke suite passed."
33 changes: 5 additions & 28 deletions .github/workflows/claude.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,6 @@
#
# IMPORTANT: Never add steps that execute code from the PR (npm install, pip install, make, etc.)
#
# `allowed_non_write_users: "*"` on pr-review and issue-handler bypasses the action's
# built-in actor-permission gate so fork PRs from external contributors get auto-reviewed
# without a maintainer having to babysit. The action's own warning calls this "extreme
# caution" territory: a malicious fork's diff gets fed to Claude, which has Bash in
# --allowedTools and access to ANTHROPIC_API_KEY + GITHUB_TOKEN. Prompt injection in the
# diff could try to coerce Claude into running an exfiltration command. The action mitigates
# with subprocess secret scrubbing (CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1, auto-set when this
# input is non-empty) + a pinned bun binary + hardened PATH. We accept the residual risk
# in exchange for not maintaining a username allowlist. If a real injection lands, tighten
# this to a literal username list (no `author_association` values supported — checked
# upstream `src/github/validation/permissions.ts`, only literal usernames or `*`).
#
# NOTE: pull_request_target uses the workflow file from the BASE branch (main), not the PR head.
# Changes to this file only take effect after merging to main.
#
Expand Down Expand Up @@ -69,16 +57,11 @@ permissions:
jobs:
# Auto-review new PRs (including forks)
pr-review:
# Temporarily disabled 2026-05 — Anthropic credit balance exhausted
# (see commit a013e384). Tracked for re-enable in
# https://github.com/amd/gaia/issues/970. To re-enable, replace the
# `if: false` line below with this commented gate:
# if: |
# github.repository == 'amd/gaia' &&
# github.event_name == 'pull_request_target' &&
# (github.event.pull_request.draft == false ||
# contains(github.event.pull_request.labels.*.name, 'ready_for_ci'))
if: false
if: |
github.repository == 'amd/gaia' &&
github.event_name == 'pull_request_target' &&
(github.event.pull_request.draft == false ||
contains(github.event.pull_request.labels.*.name, 'ready_for_ci'))
runs-on: ubuntu-latest
concurrency:
group: claude-pr-review-${{ github.event.pull_request.number }}
Expand Down Expand Up @@ -120,9 +103,6 @@ jobs:
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
# Allow fork-PR authors (no write perms) to trigger auto-review.
# See file header for the security trade-off.
allowed_non_write_users: "*"
prompt: |
Review this pull request following the custom_instructions exactly.
First read (in order): pr-diff.txt, pr-files.txt, CLAUDE.md, and the PR title/description via `gh pr view ${{ github.event.pull_request.number }}`.
Expand Down Expand Up @@ -538,9 +518,6 @@ jobs:
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
# Allow non-write users (fork-PR authors, external issue reporters) to invoke
# @claude. See file header for the security trade-off.
allowed_non_write_users: "*"
prompt: |
REPO: ${{ github.repository }}
ISSUE/PR NUMBER: ${{ github.event.issue.number }}
Expand Down
15 changes: 2 additions & 13 deletions .github/workflows/test_unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ jobs:
# pyfakefs is required by tests/unit/installer/test_uninstall_command.py
# which uses the `fs` fixture to build a fake filesystem for testing
# tiered uninstall logic cross-platform without touching the real FS.
# pytest-mock is required by the browser/filesystem tool tests.
#
# keyring + httpx + respx are required by tests/unit/connections/
# (issue #915). The in-memory keyring backend in tests/conftest.py
# avoids the SecretService daemon prerequisite on Linux runners.
uv pip install --system pytest pytest-cov pytest-asyncio pytest-mock pyfakefs \
uv pip install --system pytest pytest-cov pytest-asyncio pyfakefs \
keyring httpx respx
uv pip install --system -e ".[api]"

Expand Down Expand Up @@ -140,17 +140,6 @@ jobs:
echo " - ASR: Automatic speech recognition utilities"
echo " - TTS: Text-to-speech utilities"
echo " - InitCommand: gaia init profiles and installer logic"
echo " - FileSystemIndex: Persistent file index with FTS5 search"
echo " - FileSystemToolsMixin: browse_directory, tree, file_info, find_files, read_file, bookmark tools"
echo " - ScratchpadService: SQLite working memory for data analysis"
echo " - ScratchpadToolsMixin: create_table, insert_data, query_data, list_tables, drop_table tools"
echo " - BrowserTools: WebClient SSRF prevention, HTML extraction, downloads"
echo " - WebClient Edge Cases: parse_html fallback, extract_text, tables, links, download redirects"
echo " - Categorizer: auto_categorize, category map completeness, extension uniqueness"
echo " - ChatAgent Integration: filesystem, scratchpad, browser init/config/cleanup"
echo " - File Write Guardrails: blocked dirs, sensitive files, size limits, backup, audit"
echo " - Security Edge Cases: symlinks, audit logging, TOCTOU, prompt_overwrite"
echo " - Service Edge Cases: DB corruption rebuild, shared DB, row limits, transaction atomicity"
echo ""
echo "Integration Tests:"
echo " - DatabaseMixin + Agent: Full agent lifecycle with database"
Expand Down
2 changes: 1 addition & 1 deletion docs/deployment/code-signing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -226,5 +226,5 @@ For Windows, SignPath's OSS tier is GitHub-only — you can't sign locally. Use
- SignPath OSS Foundation: [https://signpath.io/solutions/open-source-community](https://signpath.io/solutions/open-source-community)
- SignPath GitHub Action: [https://github.com/signpath/github-action-submit-signing-request](https://github.com/signpath/github-action-submit-signing-request)
- Apple notarization docs: [https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution](https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution)
- electron-builder code signing: [https://github.com/electron-userland/electron-builder](https://github.com/electron-userland/electron-builder)
- electron-builder code signing: [https://www.electron.build/code-signing](https://www.electron.build/code-signing)
- GAIA desktop installer plan: [`docs/plans/desktop-installer.mdx`](../plans/desktop-installer)
63 changes: 1 addition & 62 deletions docs/deployment/ui.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -102,73 +102,12 @@ chmod +x gaia-agent-ui-*.AppImage
to work around the distro's AppArmor userns restriction. See
[Troubleshooting → AppImage on Linux](/reference/troubleshooting#appimage-on-linux)
for the security implications and recovery steps.
4. If you downloaded the AppImage (portable) variant, the desktop app
creates a small user shim so you can run the `gaia` CLI from a
terminal. The shim is written to `~/.local/bin/gaia` when the bundled
Python backend is installed and no other `gaia` binary exists on your
PATH. If `gaia` is still not found after installation, add `~/.local/bin`
to your `PATH` (shell restart may be required):

```bash
export PATH="$HOME/.local/bin:$PATH"
# To persist, add the above line to ~/.profile or ~/.bashrc
```

You can verify the shim exists with:

```bash
ls -l ~/.local/bin/gaia
```
5. To collect logs for a bug report:
4. To collect logs for a bug report:
```bash
gaia diagnostics
```
Attach the resulting `~/.gaia/diagnostics-*.tgz` to your GitHub issue.


## Troubleshooting — zombie backend processes

If the Electron front-end crashes or is force-quit, the Python backend
process may remain running (listening on a random port). The AppImage
now attempts to clean up stale backends on startup, but you can inspect
and terminate any leftover processes manually:

```bash
# List running GAIA backend processes
ps aux | grep -E 'python.*gaia' | grep -v grep

# Terminate a PID (SIGTERM then SIGKILL if needed)
kill <pid> || sudo kill -9 <pid>
```

If you repeatedly see leftover backends, please attach the diagnostics
bundle produced by `gaia diagnostics` to your issue and include the
output of `ps aux | grep -E 'python.*gaia'`.

## Arch Linux and AppImage notes

Arch and some rolling-release distros may ship significantly newer
glibc or system libraries than the Ubuntu runner used to produce the
AppImage. If the AppImage binary is not compatible on Arch you have
these options:

- Use the browser-based UI by running the backend manually:

```bash
lemonade-server serve
python -m gaia.ui.server
# Open http://localhost:4200
```

- Install from source or via the project `npm` package and run the
UI in development mode (see Developer Quick Start).
- Report the incompatible AppImage on GitHub so we can extend the CI
build matrix to produce an Arch-compatible artifact.

When filing an Arch/AppImage issue, include your `ldd --version`,
`cat /etc/os-release`, and the AppImage `stdout/stderr` from a terminal
run so we can diagnose glibc mismatches.

---

# Gaia Agent UI Architecture
Expand Down
Loading
Loading