Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: amd/gaia
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.17.1
Choose a base ref
...
head repository: amd/gaia
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v0.17.2
Choose a head ref
  • 17 commits
  • 135 files changed
  • 7 contributors

Commits on Apr 1, 2026

  1. fix: Claude workflow fails on fork PRs when head branch is 'main' (#685)

    ## Summary
    
    - Fix `fatal: a branch named 'main' already exists` error when reviewing
    fork PRs where the contributor's head branch is `main` (their default
    branch)
    - Fix corrupted diff base — after redirecting origin to the fork,
    `origin/$BASE_BRANCH` gets overwritten, so save the base SHA before any
    URL changes
    - Use fixed branch name `pr-head` with `-B` (force-create) instead of
    `-b $HEAD_REF` to avoid name collisions
    
    ## Root Cause
    
    When a fork PR uses `main` as its head branch ([PR
    #684](#684)):
    1. `actions/checkout` creates local `main` branch from the base repo
    2. `git checkout -b main origin/main` fails because `main` already
    exists
    3. Even if that succeeded, `git fetch origin main` (from fork) would
    overwrite `origin/main`, making the diff compare fork-vs-fork instead of
    base-vs-fork
    
    Failed run:
    https://github.com/amd/gaia/actions/runs/23859641383/job/69562473226
    
    ## Test plan
    
    - [ ] Trigger Claude review on [PR
    #684](#684) (fork PR with `main` as head
    branch) — should succeed
    - [ ] Trigger Claude review on a non-fork PR — should still work as
    before
    - [ ] Verify the generated diff in logs shows correct base-vs-fork
    comparison
    
    Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
    kovtcharov and claude authored Apr 1, 2026
    Configuration menu
    Copy the full SHA
    3f52582 View commit details
    Browse the repository at this point in the history

Commits on Apr 2, 2026

  1. feat: unified publish workflow with single approval gate (#715)

    ## Summary
    
    - Consolidate `publish_installer.yml`, `publish-npm-ui.yml`, and PyPI
    publishing into a single `publish.yml` workflow triggered by `v*` tag
    pushes
    - Single approval gate via GitHub "publish" environment — approve once,
    publish both PyPI and npm in parallel
    - `pypi.yml` reduced to CI-only build check (verifies package builds on
    every push/PR)
    - npm publish now uses the validated build artifact from the build step
    instead of rebuilding from source
    
    ## Workflow flow
    
    ```
    validate → build (pypi + npm + electron, parallel)
      → approve (single manual gate)
        → publish (pypi + npm, parallel)
          → github release (sigstore + electron artifacts)
    ```
    
    ## One-time setup required
    
    1. Create a **"publish"** GitHub environment with required reviewers
    (this is the single approval gate)
    2. Keep the **"pypi"** environment for OIDC trusted publishing, but
    remove its required reviewers
    3. Update PyPI trusted publisher config to reference `publish.yml`
    instead of `pypi.yml`
    4. npm auth is handled via npm's validated workflow mechanism (manual
    config)
    
    ## Test plan
    
    - [ ] Verify `pypi.yml` runs on push/PR and skips tag pushes
    - [ ] Verify `publish.yml` triggers on `v*` tag push
    - [ ] Verify validation catches version mismatches
    - [ ] Verify single approval gate blocks until reviewer approves
    - [ ] Verify npm publish uses pre-built artifact, not a fresh rebuild
    - [ ] Test with `workflow_dispatch` for dry-run validation
    kovtcharov authored Apr 2, 2026
    Configuration menu
    Copy the full SHA
    e4c7a5e View commit details
    Browse the repository at this point in the history

Commits on Apr 9, 2026

  1. feat: agent registry with per-session agent selection (#720)

    ## Summary
    
    - **AgentRegistry** discovers agents at boot from built-in Python
    agents, custom Python modules (`~/.gaia/agents/*/agent.py`), and YAML
    manifests (`~/.gaia/agents/*/agent.yaml`)
    - **Per-session agent routing** — sessions store `agent_type`; the
    correct agent is instantiated on cache miss
    - **Agent selector** in the chat footer and WelcomeScreen — switching
    agents mid-conversation creates a new session; switching on an empty
    session updates in place
    - **Agent name in message header** — shows "GAIA {Agent Name} |
    Thinking" during streaming and "GAIA {Agent Name} | 3m ago" after
    completion
    - **YAML manifest agents** support MCP servers, model preferences, and
    conversation starters — drop a folder in `~/.gaia/agents/` and it
    appears in the UI after a server restart
    - **Builder Agent** — "+" button opens a conversational agent creator
    that generates `agent.py` (with optional MCP scaffolding) and
    auto-refreshes the selector without a server restart
    - **DispatchQueue** boot orchestration — `_check_lemonade` and
    `_import_modules` run in parallel at startup; `_load_model` runs after
    `_check_lemonade` completes; all tasks report progress to the frontend
    - New guide: `docs/guides/custom-agent.mdx`
    
    Closes #612, #713
    
    ## Test plan
    
    - [ ] `python -m pytest tests/unit/agents/ tests/unit/chat/ui/` — all
    tests pass
    - [ ] Agent selector visible in chat footer and WelcomeScreen; switching
    mid-conversation creates new session
    - [ ] Message header shows agent name during and after streaming
    - [ ] Builder creates a working agent at
    `~/.gaia/agents/<name>/agent.py`; appears in selector immediately
    - [ ] YAML manifest in `~/.gaia/agents/<name>/agent.yaml` appears after
    server restart
    - [ ] Boot progress banner shows task names; send button disabled until
    ready
    
    ---------
    
    Co-authored-by: Tomasz Iniewicz <tomasz.iniewicz@amd.com>
    Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
    3 people authored Apr 9, 2026
    Configuration menu
    Copy the full SHA
    4d24071 View commit details
    Browse the repository at this point in the history
  2. fix: add integrity verification to RAG cache pickle loading (#447) (#722

    )
    
    ## Summary
    
      - Add `GAIA_CACHE_V1` format header and SHA-256 checksum verification
        to cache files before deserializing with `pickle.loads()`
      - Reject cache files exceeding 500 MB size limit
      - Delete corrupted or outdated cache files and re-index automatically
    - Old-format caches (pre-header) are detected and rebuilt on first load
    
      ## Context
    
      `pickle.load()` was called on cached RAG data without any validation
      (#447). A corrupted cache file would crash the RAG system permanently
      with no recovery path. This adds integrity verification at read time
      and writes a self-verifying format at cache time.
    
      Note: the diff includes an indentation change (~80 lines dedented)
    because data is now read from the file and validated before processing,
      so the processing logic moved outside the `with open()` block.
    
      ## Test plan
    
      - [x] Corrupted cache files are detected and deleted automatically
      - [x] Cache load failures trigger clean re-index, not crash
      - [x] Checksum mismatch is detected and triggers re-index
      - [x] Oversized cache files are rejected
      - [x] Old-format (pre-header) cache files are migrated on first load
      - [x] All 33 tests pass (`python -m pytest tests/test_rag.py`)
      - [x] All lint checks pass (`python util/lint.py --all`)
    albiol2004 authored Apr 9, 2026
    Configuration menu
    Copy the full SHA
    6915528 View commit details
    Browse the repository at this point in the history

Commits on Apr 10, 2026

  1. fix: drag-and-drop document upload in browser mode (#728) (#729)

    Fixes #728.
    
    ## What was broken
    
    Drag-and-drop document upload failed with *"Indexing error: Not found.
    The file or folder may have been moved or deleted."* in any browser, and
    in the packaged Electron desktop app (Electron 40).
    
    **Root cause:**
    `src/gaia/apps/webui/src/components/DocumentLibrary.tsx:265` relied on
    `(file as any).path`, an Electron-only augmentation that's `undefined`
    in every browser and was [removed in Electron
    32+](https://www.electronjs.org/blog/electron-32-0). The fallback
    `file.name` (bare filename, no directory) was POSTed to
    `/api/documents/upload-path`, which couldn't resolve it → HTTP 404 →
    misleading frontend error.
    
    ## Fix
    
    New `POST /api/documents/upload` endpoint that accepts the file content
    as multipart form data, streams it to
    `~/.gaia/documents/<shortid>_<original_name>.<ext>` with a 20 MB cap,
    dedupes by SHA-256 hash, and indexes via the standard RAG pipeline.
    Drag-and-drop in both DocumentLibrary and ChatView now use this
    endpoint. Delete cleans up server-owned files; user-owned files from
    `upload-path` are left alone.
    
    Also fixes `getFriendlyError()` in `api.ts` to prefer the backend's
    `detail` over the canned 404 string, so future upload errors surface
    meaningful messages.
    
    ### Details worth knowing
    - **On-disk filename embeds the original stem**
    (`<12-hex-id>_<sanitized_name>.<ext>`) so the agent LLM and RAG tools
    can recognize the file by its human-readable name. A pure-UUID filename
    caused the LLM to hallucinate paths (e.g.
    `C:\Users\14255\.gaia\documents\<uuid>.pdf` →
    `/Users/14255/Documents/<uuid>.pdf`) and fail tool lookups.
    - **Filename sanitizer** strips Windows-illegal chars (`<>:"/\|?*`),
    control chars, leading/trailing whitespace and dots, and caps length at
    80 chars — keeps total path well under Windows MAX_PATH.
    - **12-hex-char ID** instead of full UUID. We dedup by SHA-256 first, so
    identical-content collisions are impossible; the only theoretical
    collision is concurrent uploads of *different* content drawing the same
    ID, with probability ~1 in 1.4e14 even at 1M concurrent uploads. Saves
    24 chars per filename.
    - **Reliability**: streaming write with abort-on-overflow, try/finally
    partial cleanup (survives ClientDisconnect), atomic `os.replace`, orphan
    cleanup on indexing/db/race failures.
    - **Chat-view drop UX**: dropping onto the chat area indexes quietly
    without forcing the Document Library side panel open. Dropping onto the
    library panel itself still opens it (correct for users intentionally
    managing their library).
    
    ### Bundled cleanup
    This PR also includes a doc-consistency pass auto-applied by
    `util/lint.py --all --fix` (step 8) that aligns the supported-extension
    allowlist across backend (`utils.py`, `files.py`), frontend
    (`UnsupportedFeature.tsx`), and tests.
    
    ### What's NOT changed
    - `POST /api/documents/upload-path` is untouched — still used by the
    server-side file browser in `FileBrowser.tsx`, where the user explicitly
    picks a real filesystem path.
    - The Electron preload — deliberately not adding
    `webUtils.getPathForFile` since it's [broken for drag-drop in Electron
    30-33+](electron/electron#44600) and the blob
    path works everywhere.
    
    ### Known limitation / follow-up
    The agent LLM still occasionally cites the on-disk filename (e.g.
    `9c59c981f8e7_report.pdf`) when answering questions about a document,
    instead of the user's display name (`report.pdf`). This is because
    `src/gaia/agents/chat/tools/rag_tools.py` returns chunk metadata using
    raw filepaths from `self.rag.indexed_files` rather than translating them
    to the display name stored in `documents.filename`. **This is a
    separate, pre-existing concern in the RAG tool layer** and fixing it
    requires a focused refactor of `rag_tools.py` (~1800 lines, touches
    `query_documents`, `query_specific_file`, `summarize_document`,
    `search_indexed_chunks`, `list_indexed_documents`). Tracking it as a
    follow-up rather than expanding this PR's scope.
    
    ### Conflict notes for reviewers
    - **#723** (surface indexing failures) also touches
    `src/gaia/ui/routers/documents.py`, but edits the body of
    `upload_by_path` — this PR only adds new top-of-file constants, helpers,
    and a new `upload_document_blob` function inserted after
    `upload_by_path`. Three-way merge should be clean. Semantically, #723's
    "raise on failure" change is **more correct** under my new endpoint than
    the previous silent-0-chunk behavior.
    - **#725** (Ask Agent file indexing) touches `ChatView.tsx` in a
    disjoint line range. No conflict.
    
    ---
    
    ## Steps to reproduce the bug (before this fix)
    
    ### One-time setup
    ```bash
    git checkout main
    uv venv
    uv pip install -e ".[dev,ui]"
    cd src/gaia/apps/webui && npm install && npm run build && cd -
    ```
    
    > **Windows PowerShell users:** quote the extras → `uv pip install -e
    ".[ui]"`. Without quotes PowerShell silently strips them.
    
    ### Start the services
    ```bash
    # Terminal 1
    lemonade-server serve
    
    # Terminal 2
    gaia chat --ui
    ```
    
    ### Reproduce
    1. Open the UI in **Firefox** (most reliable repro; the bug also
    reproduces in Chrome and the packaged Electron 40 desktop app).
    2. Open DevTools → Network tab, filter on `documents`.
    3. Open or create a chat session.
    4. Drag any `.pdf`/`.txt`/`.md`/`.docx` from your file manager onto the
    Document Library drop zone or the chat area.
    5. **Observe:**
    - UI: *"Indexing error: Not found. The file or folder may have been
    moved or deleted."*
       - Network: `POST /api/documents/upload-path` → **HTTP 404**
    - Request body: `{"filepath":"report.pdf"}` (bare filename — the smoking
    gun)
       - Backend log: `HTTPException: File not found: report.pdf`
    
    ### Verify the fix
    ```bash
    git checkout kalin/fix-728-document-upload
    cd src/gaia/apps/webui && npm run build && cd -
    # Restart `gaia chat --ui`
    ```
    Repeat the drop. Expected:
    - Network: `POST /api/documents/upload` (multipart, **not**
    `upload-path`) → **HTTP 200**
    - File persisted at `~/.gaia/documents/<shortid>_report.pdf` with the
    original name embedded
    - Backend log: `Blob upload indexed: report.pdf (<N> bytes, <M> chunks)`
    - Drop the same file twice → `Blob upload dedup: report.pdf matches
    existing doc <id>` (no second file on disk)
    - Ask the agent about the doc → answers correctly using the indexed
    content
    
    ## Test plan
    
    - [x] 10 new integration tests
    (`tests/integration/test_documents_router.py`): happy path, dedup,
    empty/oversized/bad-extension/illegal-chars rejection, indexing failure
    cleanup, delete unlinks server-owned, delete preserves user-owned, 404
    on delete
    - [x] Adjacent regression sweep: 186 tests pass (files router, folder
    indexing, database, server unit tests)
    - [x] `python util/lint.py --all --fix` clean
    - [x] `tsc --noEmit` clean (no new errors in changed files)
    - [x] End-to-end smoke test via TestClient (upload → list → delete →
    file unlinked)
    - [x] **Manual (Windows + Firefox)**: drag-and-drop indexes successfully
    → ✅ validated
    - [x] **Manual**: dropped doc auto-attaches to chat session → ✅
    validated
    - [x] **Manual**: dedup short-circuit verified → ✅ validated
    - [x] **Manual**: delete cleanup verified for both server-owned and
    user-owned files → ✅ validated
    - [x] **Manual**: agent answers questions correctly using the indexed
    document → ✅ validated (display-name citation polish tracked as
    follow-up; see "Known limitation" above)
    
    ---------
    
    Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
    kovtcharov and claude authored Apr 10, 2026
    Configuration menu
    Copy the full SHA
    d2ffb96 View commit details
    Browse the repository at this point in the history
  2. feat: desktop installer for GAIA Agent UI (#530) (#731)

    Closes #530.
    
    Ships GAIA as a real desktop app with one-click installers — the primary
    install path for non-developer end users.
    
    ## What users get
    
    **One-click install on every platform.** Download `gaia-agent-ui-*.exe`
    (Windows), `.dmg` (macOS), `.deb` or `.AppImage` (Linux) from GitHub
    Releases. Double-click and you're done. No Python, no `pip`, no
    terminal.
    
    **Automatic backend setup on first launch.** The app shows a progress
    dialog while it downloads `uv`, creates a Python venv, installs the GAIA
    backend, and starts Lemonade Server. About 5–10 minutes the first time,
    instant on every launch after. If anything fails, users see an error
    dialog with a Retry button, a "Manual install" link, and a log file path
    — no more dead-end *"Install with: pip install amd-gaia"*.
    
    **Auto-updates in the background.** GAIA checks GitHub Releases on
    launch and every few hours. When a new version is available, users see a
    "Restart to update" prompt — same flow as Slack, VS Code, etc. No manual
    reinstalls.
    
    **Native uninstall.** Add or Remove Programs / drag to Trash / `apt
    remove` all work as expected. User data in `~/.gaia/` is preserved
    unless explicitly purged. A `gaia uninstall` CLI offers tiered cleanup
    (`--venv`, `--purge`, `--purge-lemonade`, `--purge-models`,
    `--purge-hf-cache`, `--dry-run`) for power users.
    
    **Windows autostart by default.** GAIA starts in the system tray when
    you sign in to Windows, matching the Slack/Discord/Zoom convention.
    Disable via Task Manager → Startup or the in-app tray menu.
    
    **Trusted installers (when secrets land).** Code-signing scaffolding is
    in place for SignPath (Windows) and Apple Developer ID + notarization
    (macOS). Activates with zero code changes once #732 and #733 unblock —
    no more SmartScreen / Gatekeeper warnings.
    
    ## Naming
    
    Display name is **GAIA** (dock, Start Menu, title bar, tray). Electron
    binary is `gaia-desktop` (avoids collision with the Python CLI `gaia`).
    Download artifacts use `gaia-agent-ui-*` for URL stability.
    
    ## Verification
    
    - Windows NSIS installer tested end-to-end on real hardware: install →
    first-launch bootstrap (uv + venv + pip + gaia init + Lemonade) → chat
    UI loads → functional
    - Local macOS DMG verified: mounted, code-signed, entitlements
    confirmed, first-launch bootstrap completes
    - Cross-platform CI green on Windows + macOS + Linux via the new
    `build-installers.yml` workflow (51/51 checks passing)
    - 3 automated code review passes: 19 issues found and fixed (name
    collisions, stale refs, orphaned registry keys, missing require, cwd
    bug, frontend loading bug, API_BASE file:// fix, doc sync)
    - 42 unit tests for `gaia uninstall` (containment guard, log handler
    cleanup, silent-purge refusal, Lemonade python resolution, exit codes,
    GAIA_HOME env var)
    
    ## Test plan
    
    - [x] Smoke test on real Windows: download → install → first-run → chat
    UI loads
    - [ ] Smoke test on real macOS: mount DMG → drag to Applications →
    first-run backend install → single-instance lock → uninstall
    - [ ] Smoke test on real Linux: `.deb` + `.AppImage`
    - [ ] Re-verify after SignPath / Apple Developer ID secrets land (#732,
    #733)
    
    ## Follow-ups
    
    - #732 — SignPath OSS application for Windows code signing
    - #733 — AMD Apple Developer ID for macOS notarization
    - #734 — R2 / amd-gaia.ai distribution mirror
    
    ---------
    
    Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
    kovtcharov and claude authored Apr 10, 2026
    Configuration menu
    Copy the full SHA
    f5b0d39 View commit details
    Browse the repository at this point in the history
  3. fix(linux): chrome-sandbox SUID and gaia init non-interactive mode (#743

    )
    
    Fixes two critical bugs found during end-to-end install testing on
    Ubuntu 24.04 (amd64), testing against PR #731.
    
    ## Bug 1: chrome-sandbox missing SUID bit
    
    **Symptom:** App crashes immediately after `apt install` with:
    ```
    FATAL: The SUID sandbox helper binary was found, but is not configured correctly.
    Rather than run without sandboxing I'm aborting now. You need to make sure that
    /opt/GAIA/chrome-sandbox is owned by root and has mode 4755.
    ```
    
    **Root cause:** `electron-builder` packages `chrome-sandbox` with mode
    `755`. Chromium's sandbox helper requires `4755` (setuid root) to
    function. Without it, no user can launch the app after a clean install.
    
    **Fix:** `installer/debian/postinst` now sets `chown root:root` + `chmod
    4755` on `/opt/GAIA/chrome-sandbox` during package configuration, which
    runs as root via `apt`.
    
    ## Bug 2: Model download silently skipped — app crashes when user types
    
    **Symptom:** Bootstrap completes and reports `ready`, but Qwen3-0.6B is
    never downloaded. Lemonade has no model loaded, so the app crashes when
    the user sends their first message.
    
    **Root cause:** `backend-installer.cjs` runs `gaia init --profile
    minimal` with piped stdio (for log streaming). With no TTY attached,
    `gaia init`'s interactive prompts ("Continue? [Y/n]:" and "Run model
    verification? [Y/n]:") receive EOF and answer themselves as "Skipping".
    The non-zero-ish exit is treated as non-fatal, so state reaches `ready`
    despite no model existing.
    
    **Fix:** Pass `--yes` to `gaia init` so prompts are auto-answered. The
    flag already exists for this purpose.
    
    ## Testing
    
    Both bugs reproduced on Ubuntu 24.04.4 LTS (x86_64, kernel 6.17) with
    the `.deb` from CI run
    [24255947495](https://github.com/amd/gaia/actions/runs/24255947495).
    Verified manually:
    - Before fix: immediate crash on launch (Bug 1), silent model skip +
    crash on chat (Bug 2)
    - After applying patches locally: app launches, bootstrap downloads
    model, chat works
    
    Closes part of #530.
    itomek authored Apr 10, 2026
    Configuration menu
    Copy the full SHA
    df7a0ae View commit details
    Browse the repository at this point in the history
  4. feat: MCP tool execution visualization in activity history (#717)

    ## Summary
    
    Closes #712
    
    - MCP tool calls in the Agent Activity panel now show a purple **"via
    {server}"** badge identifying the MCP server
    - **Latency** (in ms) is displayed in the collapsed tool header,
    measured at the SSE handler layer via `time.monotonic()`
    - MCP tool cards start **collapsed by default** (native tools still
    auto-expand)
    - **Filter bar** appears when 2+ tool steps exist — filter by tool name
    text or status (All/Success/Error)
    - Server name resolved via `_TOOL_REGISTRY` lookup (no fragile prefix
    parsing)
    - No new SSE event types, no DB migration, no new API endpoints
    
    ## Changes
    
    | File | Change |
    |------|--------|
    | `src/gaia/ui/sse_handler.py` | `mcp_server` on `tool_start`,
    `latency_ms` on `tool_result` |
    | `src/gaia/ui/_chat_helpers.py` | `mcpServer`/`latencyMs` in captured
    steps |
    | `src/gaia/ui/models.py` | New fields on `AgentStepResponse` |
    | `src/gaia/apps/webui/src/types/index.ts` | Extend `AgentStep` +
    `StreamEvent` |
    | `src/gaia/apps/webui/src/components/ChatView.tsx` | Forward
    `mcp_server`/`latency_ms` in event handlers |
    | `src/gaia/apps/webui/src/components/AgentActivity.tsx` | MCP meta,
    badge, latency, filter bar, collapsed-by-default |
    | `src/gaia/apps/webui/src/components/AgentActivity.css` | Filter bar,
    MCP badge, latency styles |
    | `tests/unit/chat/ui/test_sse_handler.py` | 7 new MCP visualization
    tests |
    | `tests/unit/chat/ui/test_models.py` | 4 new AgentStepResponse tests |
    
    ## Test plan
    
    - [x] 216 unit tests pass (`python -m pytest tests/unit/chat/ui/`)
    - [x] Frontend builds clean (`npm run build`)
    - [x] Lint passes (`python util/lint.py --all --fix`)
    - [x] Manual: `gaia chat --ui` → configure MCP server → trigger tool
    calls → verify badge/latency/filter/collapse
    - [x] Manual: Refresh page → verify tool traces persist in session
    
    ## Images
    <img width="813" height="751" alt="image"
    src="https://github.com/user-attachments/assets/82f6d6d1-a272-4c30-a5cc-9aebfe64b92f"
    />
    
    ---------
    
    Co-authored-by: Tomasz Iniewicz <infancy_shred.0d@icloud.com>
    Co-authored-by: Tomasz Iniewicz <itomek@users.noreply.github.com>
    Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
    4 people authored Apr 10, 2026
    Configuration menu
    Copy the full SHA
    83f5148 View commit details
    Browse the repository at this point in the history
  5. Release v0.17.2 (#744)

    Release notes for v0.17.2. See
    [docs/releases/v0.17.2.mdx](https://github.com/amd/gaia/blob/v0.17.2-release/docs/releases/v0.17.2.mdx)
    for the full body.
    
    **Headline features:**
    - One-click desktop installers for Windows, macOS, and Linux (#731 +
    #743)
    - Customizable agents and Builder Agent (#720)
    - MCP tool execution visibility in Agent Activity panel (#717)
    
    **Security:** RAG cache integrity verification (#722, closes #447)
    
    **Bug fixes:** drag-and-drop upload in any browser (#729), Linux install
    fixes (#743)
    
    **Release & CI:** unified publish workflow (#715), Claude review on fork
    PRs (#685), npm OIDC fix (#683), webui package.json sync (#682)
    
    Full changelog: v0.17.1...v0.17.2
    
    ---------
    
    Co-authored-by: Tomasz Iniewicz <tomasz@iniewicz.com>
    itomek and Tomasz Iniewicz authored Apr 10, 2026
    Configuration menu
    Copy the full SHA
    cd81adc View commit details
    Browse the repository at this point in the history

Commits on Apr 11, 2026

  1. fix(ci): indent heredoc in publish.yml to fix startup_failure (#747)

    ## Summary
    
    - The `Publish Release` workflow failed with `startup_failure` (0 jobs,
    instant failure) on the v0.17.2 tag push:
    https://github.com/amd/gaia/actions/runs/24267844380
    - **Root cause:** The heredoc body in the `github-release` job's
    "Extract release notes" step was at column 0 (no indentation), which
    broke out of the `run: |` YAML block scalar. The YAML parser interpreted
    `- **Windows**` as a sequence item with `*Windows` as an alias
    reference, causing a parse error before any job could start.
    - **Fix:** Indent the heredoc body to 10 spaces to match the block
    scalar's indentation level. YAML strips the leading spaces
    automatically, so bash still receives the content at column 0 — no
    change to the generated release body.
    
    ## Test plan
    
    - [x] `yaml-lint` passes on `publish.yml` (was failing before the fix)
    - [ ] Re-tag v0.17.2 (or use `workflow_dispatch`) to verify the publish
    workflow starts successfully
    
    ðŸĪ– Generated with [Claude Code](https://claude.com/claude-code)
    
    Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
    kovtcharov and claude authored Apr 11, 2026
    Configuration menu
    Copy the full SHA
    a786080 View commit details
    Browse the repository at this point in the history
  2. fix(ci): grant contents:write for build-electron in publish workflow (#â€Ķ

    â€Ķ748)
    
    ## Summary
    
    - Fixes the `startup_failure` on the Publish Release workflow:
    https://github.com/amd/gaia/actions/runs/24278877956
    - **Root cause:** `build-electron-apps.yml` declares `permissions:
    contents: write` at its top level. When called as a reusable workflow
    from `publish.yml`, the calling `build-electron` job only had `contents:
    read` (inherited from publish.yml's workflow-level permissions). GitHub
    Actions validates this at startup and rejects the run before any jobs
    start.
    - **Fix:** Add explicit `permissions: contents: write` to the
    `build-electron` job in publish.yml so it matches what the reusable
    workflow declares.
    
    > **Note:** The previous PR #747 fixed a YAML block scalar issue
    (heredoc indentation) that was also causing a parse error. This PR fixes
    the second startup_failure — the permissions mismatch discovered from
    the GitHub Actions error annotation.
    
    ## Test plan
    
    - [ ] Merge, move v0.17.2 tag, verify Publish Release workflow starts
    and reaches the Validate step
    
    ðŸĪ– Generated with [Claude Code](https://claude.com/claude-code)
    
    Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
    kovtcharov and claude authored Apr 11, 2026
    Configuration menu
    Copy the full SHA
    bbf372e View commit details
    Browse the repository at this point in the history
  3. fix(ci): skip macOS code signing when APPLE_ID is not set (#749)

    ## Summary
    
    - Fixes the macOS DMG build failure in the Publish Release workflow:
    https://github.com/amd/gaia/actions/runs/24278980001
    - **Root cause:** electron-builder auto-skips code signing for PR builds
    (`Current build is a part of pull request, code signing will be
    skipped`) but NOT for tag pushes. Without valid signing secrets, it
    tries to sign with empty credentials and fails with `âĻŊ
    .../src/gaia/apps/webui not a file`.
    - **Fix:** Pass `--config.mac.identity=null` when `APPLE_ID` is not set,
    explicitly telling electron-builder to skip signing. Windows and Linux
    builds are unaffected (they don't attempt signing without their
    respective secrets).
    
    > This is the third fix for the v0.17.2 publish pipeline, after #747
    (YAML heredoc indentation) and #748 (reusable workflow permissions).
    
    ## Test plan
    
    - [x] The PR itself triggers `build-installers.yml` (via `paths:`
    filter) — the macOS job will validate the fix
    - [ ] After merge, move v0.17.2 tag and re-trigger publish
    
    ðŸĪ– Generated with [Claude Code](https://claude.com/claude-code)
    
    Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
    kovtcharov and claude authored Apr 11, 2026
    Configuration menu
    Copy the full SHA
    4383e07 View commit details
    Browse the repository at this point in the history
  4. fix(ui): add explicit types to terminalStore callbacks (#750)

    ## Summary
    
    - Fixes TypeScript compilation failure in the `Publish to npm` job:
    https://github.com/amd/gaia/actions/runs/24279178148/job/70898457497
    - `terminalStore.ts` callbacks (`setPaused`, `setActiveTab`,
    `openTerminal`, `setShowTerminal`) relied on Zustand type inference for
    parameter types, but `tsc` flagged them as implicit `any` during the
    build
    - Added explicit parameter type annotations matching the `TerminalState`
    interface
    
    ## Test plan
    
    - [x] `npx tsc --noEmit` passes locally with zero errors
    - [ ] Merge, move tag, verify npm publish step passes
    
    ðŸĪ– Generated with [Claude Code](https://claude.com/claude-code)
    
    Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
    kovtcharov and claude authored Apr 11, 2026
    Configuration menu
    Copy the full SHA
    2e6553d View commit details
    Browse the repository at this point in the history
  5. fix(ci): skip prepublishOnly during npm publish step (#751)

    ## Summary
    
    - Fixes the `Publish to npm` job failure:
    https://github.com/amd/gaia/actions/runs/24279365243/job/70899004478
    - **Root cause:** `npm publish` triggers `prepublishOnly` → `tsc && vite
    build`, but the job installs only production deps (`--omit=dev`). `tsc`
    fails because `@types/react`, `typescript`, etc. are missing.
    - **Fix:** Add `--ignore-scripts` to `npm publish`. The dist/ is already
    pre-built in the `build-npm` job and downloaded as an artifact — the
    prepublishOnly rebuild is redundant.
    
    > Fix #5 for the v0.17.2 publish pipeline, after #747 (YAML indent),
    #748 (permissions), #749 (macOS signing), #750 (terminalStore types).
    
    ## Test plan
    
    - [ ] Merge, move tag, verify npm publish succeeds
    
    ðŸĪ– Generated with [Claude Code](https://claude.com/claude-code)
    
    Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
    kovtcharov and claude authored Apr 11, 2026
    Configuration menu
    Copy the full SHA
    60728d0 View commit details
    Browse the repository at this point in the history
  6. fix(ci): add npm environment for OIDC trusted publishing (#753)

    ## Summary
    
    - Fixes `ENEEDAUTH` in the `Publish to npm` job:
    https://github.com/amd/gaia/actions/runs/24279785278/job/70899991808
    - **Root cause:** The old `publish-npm-ui.yml` workflow used
    `environment: npm` which carries the OIDC claims npm needs for trusted
    publishing. The new unified `publish.yml` dropped this block, so npm
    rejected auth.
    - **Fix:** Restore the `environment: npm` block and the `npm install -g
    npm@latest` upgrade step, both matching the old working workflow.
    
    ## Test plan
    
    - [ ] Merge, move tag, verify npm publish authenticates and publishes
    successfully
    
    ðŸĪ– Generated with [Claude Code](https://claude.com/claude-code)
    
    Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
    kovtcharov and claude authored Apr 11, 2026
    Configuration menu
    Copy the full SHA
    c3fc32b View commit details
    Browse the repository at this point in the history
  7. fix(ci): remove npm upgrade step that corrupts npm on Node 22 (#755)

    ## Summary
    
    - Fixes `Cannot find module 'promise-retry'` in the npm publish job:
    https://github.com/amd/gaia/actions/runs/24280075274/job/70900655694
    - **Root cause:** `npm install -g npm@latest` replaces the bundled npm
    with a version incompatible with the runner's Node 22 layout, corrupting
    npm's own dependencies.
    - **Fix:** Remove the upgrade step. Node 22 ships with npm 10+ which
    already supports OIDC trusted publishing.
    
    ## Test plan
    
    - [ ] Merge, move tag, verify npm publish works
    
    ðŸĪ– Generated with [Claude Code](https://claude.com/claude-code)
    
    Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
    kovtcharov and claude authored Apr 11, 2026
    Configuration menu
    Copy the full SHA
    49db9a3 View commit details
    Browse the repository at this point in the history
  8. fix(ci): add registry-url for npm OIDC trusted publishing (#756)

    ## Summary
    
    - Fixes `ENEEDAUTH` in npm publish:
    https://github.com/amd/gaia/actions/runs/24280576961
    - **Root cause:** `setup-node` without `registry-url` never creates the
    `.npmrc` that maps `NODE_AUTH_TOKEN` to the npm registry. npm's OIDC
    trusted publishing needs this to authenticate.
    - **Note:** The old `publish-npm-ui.yml` was never actually run (zero
    successful runs in history) — v0.17.0 and v0.17.1 were published outside
    CI. So the old workflow's lack of `registry-url` was an untested bug
    too.
    - **Fix:** Add `registry-url: 'https://registry.npmjs.org'` to
    `setup-node`.
    
    ## Test plan
    
    - [ ] Merge, move tag, verify npm publish authenticates and succeeds
    
    ðŸĪ– Generated with [Claude Code](https://claude.com/claude-code)
    
    Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
    kovtcharov and claude authored Apr 11, 2026
    Configuration menu
    Copy the full SHA
    60bfaae View commit details
    Browse the repository at this point in the history
Loading