Skip to content
This repository was archived by the owner on Jul 27, 2026. It is now read-only.

fix(frontend): do not gate the skills modal on runtime readiness - #1122

Merged
hieptl merged 3 commits into
mainfrom
hieptl/app-2155
Jun 4, 2026
Merged

hieptl merged 3 commits into
mainfrom
hieptl/app-2155

Conversation

@hieptl

@hieptl hieptl commented Jun 4, 2026 •

Copy link
Copy Markdown
Contributor
  • A human has tested these changes.

Why

Problem

Opening the Available Skills modal from the chat input's + menu on the home page shows a loading spinner with "Waiting for runtime to start…" that never completes. The modal is unusable from the home page on both local and cloud backends, and from any conversation whose execution status is null (e.g. a stopped cloud sandbox).

Steps to Reproduce

  1. Start the development server: npm run dev
  2. On the home page, click the plus (+) icon in the chat input to open the context menu
  3. Select "Show Available Skills"

Current Behavior

The modal opens, but the spinner ("Waiting for runtime to start…") spins indefinitely. No skills are ever listed and no error is shown.

Expected Behavior

  • The modal loads and displays the list of available skills
  • If the list cannot be loaded, a clear failure message is shown instead of an endless spinner

Root Cause

SkillsModal gates its entire body on isAgentReady, derived from useAgentState(), which maps a null execution status to AgentState.LOADING. With no conversation (home page) — or a conversation whose status stays null — that state never changes, so the waiting branch renders forever.

The gate is vestigial: it dates from when skills were loaded from the conversation runtime (loadSkillsForConversation, enabled: !!executionStatus). Since PR #362 the skills come from a static catalog (SkillsService.getSkills — agent-server SkillsClient locally, /api/v1/skills/search on cloud) that requires no conversation or runtime. The Skills settings page and the slash-command menu already consume the same catalog ungated.

Fix

Remove the runtime-readiness gate from SkillsModal and let the skills query's own states drive the UI (loading → spinner, error → "Failed to fetch skills…", data → grouped catalog). Delete the orphaned SkillsRuntimeWaitingState component.

Acceptance Criteria

  • Opening Available Skills from the home page + menu lists the skills catalog
  • When the skills fetch fails, the modal shows the fetch-error message instead of hanging
  • Works on local and cloud backends, and in conversations regardless of runtime state
  • Regression tests cover the home-page and fetch-failure paths

Summary

Fixes the Available Skills modal spinning forever on "Waiting for runtime to start…" when opened from the home page's chat input + menu (reproducible on local and cloud backends), and in any conversation whose execution status is null.

Problem

SkillsModal only rendered its content once curAgentState left LOADING/INIT:

const isAgentReady = ![AgentState.LOADING, AgentState.INIT].includes(curAgentState);
...
{!isAgentReady ? <SkillsRuntimeWaitingState /> : ...}

useAgentState() maps a null execution status to AgentState.LOADING. On the home page no conversation exists, so the status is null forever → the waiting spinner never resolves.

Root Cause

The gate is a leftover from when skills were loaded from the conversation runtime (loadSkillsForConversation, gated on executionStatus). Since #362 the modal reads a static catalog via SkillsService.getSkills() — agent-server SkillsClient locally, /api/v1/skills/search via the cloud proxy on cloud backends — which needs no conversation or runtime. The Skills settings page (useSkills()) and the slash-command menu (useConversationSkills()) already consume the same catalog with no such gate.

Changes

  • src/components/features/conversation-panel/skills-modal.tsx — remove the isAgentReady gate; the skills query's own states now drive the UI (isLoading → loading state, isError → "Failed to fetch skills. Please try again later.", data → grouped catalog). One internal change fixes all three render sites (chat + menu, tools menu, conversation-title menu).
  • src/components/features/conversation-panel/skills-runtime-waiting-state.tsx — deleted (orphaned; the DIFF_VIEWER$WAITING_FOR_RUNTIME i18n key remains in use by diff-viewer components).
  • __tests__/components/modals/skills/skill-modal.test.tsx — remove the useAgentState mock and the test asserting the old gating behavior; add regression tests (mocking SkillsService, not hooks):
    • displays the skills catalog when opened with no active conversation (home page)
    • surfaces the fetch-error message when the catalog cannot be loaded

Deliberately not added: an enabled: !!conversation.data gate on the skills query — that would reintroduce the hang on the home page.

Issue Number

Resolves #2092

How to Test

  1. Start the development server: npm run dev
  2. On the home page, click the plus (+) icon in the chat input to open the context menu
  3. Select "Show Available Skills"

Video/Screenshots

app-2155.mov

Type

  • Bug fix
  • Feature
  • Refactor
  • Breaking change
  • Docs / chore

🐳 Docker images for this PR

• GHCR package: https://github.com/OpenHands/agent-canvas/pkgs/container/agent-canvas

Component Value
Image ghcr.io/openhands/agent-canvas
Architectures amd64, arm64
Agent Server ghcr.io/openhands/agent-server:1.24.0-python
Automation openhands-automation==1.0.0a6
Commit c5d69ae41a0dfda44a712011f04c9652a71da7d4

Pull (multi-arch manifest)

# Multi-arch manifest — Docker automatically pulls the correct architecture
docker pull ghcr.io/openhands/agent-canvas:sha-c5d69ae

Run

docker run -it --rm \
  -p 8000:8000 \
  ghcr.io/openhands/agent-canvas:sha-c5d69ae

All tags pushed for this build

ghcr.io/openhands/agent-canvas:sha-c5d69ae-amd64
ghcr.io/openhands/agent-canvas:hieptl-app-2155-amd64
ghcr.io/openhands/agent-canvas:pr-1122-amd64
ghcr.io/openhands/agent-canvas:sha-c5d69ae-arm64
ghcr.io/openhands/agent-canvas:hieptl-app-2155-arm64
ghcr.io/openhands/agent-canvas:pr-1122-arm64
ghcr.io/openhands/agent-canvas:sha-c5d69ae
ghcr.io/openhands/agent-canvas:hieptl-app-2155
ghcr.io/openhands/agent-canvas:pr-1122

About Multi-Architecture Support

  • Each tag (e.g., sha-c5d69ae) is a multi-arch manifest supporting both amd64 and arm64
  • Docker automatically pulls the correct architecture for your platform
  • Individual architecture tags (e.g., sha-c5d69ae-amd64) are also available if needed

@hieptl hieptl self-assigned this Jun 4, 2026
@vercel

vercel Bot commented Jun 4, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agent-canvas Ready Ready Preview, Comment Jun 4, 2026 2:33pm

Request Review

@tofarr tofarr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🍰

@hieptl
hieptl merged commit 0631ade into main Jun 4, 2026
17 checks passed
@hieptl
hieptl deleted the hieptl/app-2155 branch June 4, 2026 14:40
@openhands-release-bot openhands-release-bot Bot added the released: v1.2.0 Shipped in v1.2.0 label Jul 9, 2026
@openhands-release-bot

Copy link
Copy Markdown
Contributor

🚀 Released in v1.2.0.

github-actions Bot added a commit that referenced this pull request Jul 9, 2026
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

📸 Snapshot Test Report

Warning

Snapshot comparison step crashed (timeout, OOM, or runner error) — diff results below may be incomplete or absent.
Check the CI logs for the full error output (look for the "Run snapshot comparison" step).

✅ No baseline found on main — all 73 snapshots are new and will become the baseline once this PR merges.

Category Count
🔴 Changed 0
🆕 New 73
✅ Unchanged 0
Total 73
🆕 New snapshots (73)

These snapshots have no baseline on main and will become the new baseline once this PR merges.

archived-conversation — 3 snapshots

conversation-panel-with-archived-badges

new snapshot

conversation-view-archived

new snapshot

conversation-view-sandbox-error

new snapshot

automations — 4 snapshots

automations-delete-modal

new snapshot

automations-list-active-inactive

new snapshot

automations-no-automations

new snapshot

automations-search-no-results

new snapshot

backends-extended — 19 snapshots

backend-add-blank-disabled

new snapshot

backend-add-cloud-advanced-open

new snapshot

backend-add-cloud-no-key-disabled

new snapshot

backend-add-cloud-with-key-enabled

new snapshot

backend-add-form-partially-filled

new snapshot

backend-add-invalid-url-disabled

new snapshot

backend-add-local-ready

new snapshot

backend-add-name-only-disabled

new snapshot

backend-add-two-column-layout

new snapshot

backend-add-whitespace-host-disabled

new snapshot

backend-after-switch

new snapshot

backend-cancel-nothing-saved

new snapshot

backend-dropdown-two-backends

new snapshot

backend-edit-prefilled

new snapshot

backend-manage-after-removal

new snapshot

backend-manage-two-listed

new snapshot

backend-remove-cancelled

new snapshot

backend-remove-confirmation

new snapshot

backend-switch-overlay

new snapshot

backends — 3 snapshots

backend-add-modal

new snapshot

backend-manage-modal

new snapshot

backend-selector-open

new snapshot

changes-tab — 3 snapshots

changes-deleted-file

new snapshot

changes-diff-viewer

new snapshot

changes-empty

new snapshot

collapsible-thinking — 4 snapshots

reasoning-content-collapsed

new snapshot

reasoning-content-expanded

new snapshot

think-action-collapsed

new snapshot

think-action-expanded

new snapshot

mcp-page — 11 snapshots

mcp-custom-server-1-editor-open

new snapshot

mcp-custom-server-2-url-filled

new snapshot

mcp-custom-server-3-all-filled

new snapshot

mcp-custom-server-4-installed

new snapshot

mcp-custom-server-editor

new snapshot

mcp-empty-installed

new snapshot

mcp-search-filtered

new snapshot

mcp-slack-install-1-marketplace

new snapshot

mcp-slack-install-2-modal

new snapshot

mcp-slack-install-3-filled

new snapshot

mcp-slack-install-4-installed

new snapshot

onboarding — 4 snapshots

onboarding-step-0-check-backend

new snapshot

onboarding-step-1-choose-agent

new snapshot

onboarding-step-2-setup-llm

new snapshot

onboarding-step-3-say-hello

new snapshot

projects-workspace-browser

projects-workspace-browser

new snapshot

settings-page — 5 snapshots

add-backend-modal

new snapshot

analytics-consent-modal

new snapshot

home-screen

new snapshot

settings-app-page

new snapshot

settings-page

new snapshot

settings-secrets — 5 snapshots

secrets-add-form-filled

new snapshot

secrets-add-form

new snapshot

secrets-after-save

new snapshot

secrets-delete-confirm

new snapshot

secrets-list

new snapshot

settings-verification — 3 snapshots

condenser-settings

new snapshot

verification-settings-off

new snapshot

verification-settings-on

new snapshot

sidebar — 3 snapshots

sidebar-collapsed

new snapshot

sidebar-conversation-panel

new snapshot

sidebar-filter-menu

new snapshot

skills-page — 5 snapshots

skills-empty

new snapshot

skills-loaded

new snapshot

skills-no-match

new snapshot

skills-search-filtered

new snapshot

skills-type-filter

new snapshot


Generated by the Snapshot Tests workflow. This comment was created by an AI agent (OpenHands) on behalf of the repo maintainers.

This branch was successfully deployed

1 active deployment
Preview — c5d69ae4 Deployed Jun 4, 2026 by vercel[bot]
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

released: v1.2.0 Shipped in v1.2.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: "Use Skills" modal occasionally hangs on loading screen

2 participants