diff --git a/.github/workflows/chat-proxy-prod.yml b/.github/workflows/chat-proxy-prod.yml index 7b9e636f..7b844d5c 100644 --- a/.github/workflows/chat-proxy-prod.yml +++ b/.github/workflows/chat-proxy-prod.yml @@ -1,6 +1,9 @@ name: Chat Proxy Production Deploy on: + push: + branches: + - main pull_request: types: [closed] branches: @@ -9,7 +12,7 @@ on: jobs: deploy-prod: - if: github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true + if: github.event_name == 'workflow_dispatch' || github.event_name == 'push' || github.event.pull_request.merged == true runs-on: ubuntu-latest env: HYPHA_SERVER_URL: ${{ vars.HYPHA_SERVER_URL }} @@ -45,6 +48,7 @@ jobs: --app-id "$PROD_APP_ID" \ --non-fatal-start \ --health-check \ + --check-request-url \ --model gpt-5-mini - name: Roll back to previous commit if deploy failed @@ -55,6 +59,7 @@ jobs: --app-id "$PROD_APP_ID" \ --non-fatal-start \ --health-check \ + --check-request-url \ --model gpt-5-mini - name: Ensure production health @@ -63,9 +68,9 @@ jobs: --app-id "$PROD_APP_ID" \ --model gpt-5-mini \ --timeout 120 \ - --check-search \ - --search-query "mouse tumor" \ - --search-limit 5 + --check-request-url \ + --request-url "https://beta.bioimagearchive.org/search/search/fts?query=mouse%20OR%20tumor" \ + --request-attempts 5 - name: Compute merged branch app ids if: github.event_name == 'pull_request' diff --git a/e2e/agent-chat-resilience.spec.ts b/e2e/agent-chat-resilience.spec.ts index 8b6c1702..cf80d75d 100644 --- a/e2e/agent-chat-resilience.spec.ts +++ b/e2e/agent-chat-resilience.spec.ts @@ -110,10 +110,18 @@ test.describe('BioImage Finder chat resilience', () => { await expect(page.getByRole('button', { name: 'Cancel' })).toBeVisible({ timeout: 20_000 }); await page.waitForTimeout(15_000); - await expect(page.getByRole('button', { name: 'Cancel' })).toBeVisible(); - await page.getByRole('button', { name: 'Cancel' }).click(); - await expect(page.locator('text=Request cancelled by user.')).toBeVisible({ timeout: 20_000 }); - await expect(page.getByRole('button', { name: 'Cancel' })).toHaveCount(0); + + const cancelButton = page.getByRole('button', { name: 'Cancel' }); + const cancelStillVisible = await cancelButton.isVisible().catch(() => false); + + if (cancelStillVisible) { + await cancelButton.click(); + await expect(page.locator('text=Request cancelled by user.')).toBeVisible({ timeout: 20_000 }); + await expect(cancelButton).toHaveCount(0); + } else { + await expect(cancelButton).toHaveCount(0); + await expect(page.locator('textarea[placeholder*="Type a message"]')).toBeEnabled({ timeout: 20_000 }); + } await page.evaluate(() => { (globalThis as any).__chatProxyTestMode = undefined; diff --git a/scripts/deploy_chat_proxy.py b/scripts/deploy_chat_proxy.py index 1bc548a0..a9cef841 100644 --- a/scripts/deploy_chat_proxy.py +++ b/scripts/deploy_chat_proxy.py @@ -85,6 +85,27 @@ def parse_args() -> ArgumentParser: default="", help="Optional response substring required by health check", ) + parser.add_argument( + "--check-request-url", + action="store_true", + help="Verify proxy.resolve_url is available and can reach the configured request URL", + ) + parser.add_argument( + "--request-url", + default="https://beta.bioimagearchive.org/search/search/fts?query=mouse%20OR%20tumor", + help="URL used for resolve_url health checks", + ) + parser.add_argument( + "--request-attempts", + type=int, + default=3, + help="Number of resolve_url probes during health checks", + ) + parser.add_argument( + "--compare-direct", + action="store_true", + help="Also compare proxy.resolve_url probes with direct requests", + ) return parser @@ -141,6 +162,12 @@ def main() -> int: ] if args.expected_substring: health_cmd.extend(["--expected-substring", args.expected_substring]) + if args.check_request_url: + health_cmd.append("--check-request-url") + health_cmd.extend(["--request-url", args.request_url]) + health_cmd.extend(["--request-attempts", str(args.request_attempts)]) + if args.compare_direct: + health_cmd.append("--compare-direct") first_health_exit = run(health_cmd, check=False) if first_health_exit != 0: diff --git a/src/pages/AgentPage.tsx b/src/pages/AgentPage.tsx index 63313447..d35366cb 100644 --- a/src/pages/AgentPage.tsx +++ b/src/pages/AgentPage.tsx @@ -923,7 +923,9 @@ const AgentPage: React.FC = () => { _rkwargs: true }); - const mappedAgents: Agent[] = initialAgents.map((art: any) => ({ + const limitedAgents = initialAgents.filter((art: any) => art.id === defaultAgentId); + + const mappedAgents: Agent[] = limitedAgents.map((art: any) => ({ id: art.id, name: art.manifest?.name || art.alias || 'Unnamed Agent', description: art.manifest?.description || 'No description provided.', @@ -1045,7 +1047,7 @@ const AgentPage: React.FC = () => { // We look for a requirements.txt file to install extra dependencies // Also check manifest for dependencies? const reqFile = files.find((f: any) => f.name === 'requirements.txt'); - let packages: string[] = ["hypha-rpc==0.21.19", "openai"]; // Always install hypha-rpc and openai + let packages: string[] = ["hypha-rpc==0.21.19"]; // Always install hypha-rpc if (reqFile) { console.log("Installing dependencies from requirements.txt..."); @@ -1689,7 +1691,9 @@ _install_httpx_proxy_patch() console.log("AgentPage: Agents found:", initialAgents); // We assume all found agents are "online" (available to start via proxy) - const mappedAgents: Agent[] = initialAgents.map((art: any) => { + const limitedAgents = initialAgents.filter((art: any) => art.id === defaultAgentId); + + const mappedAgents: Agent[] = limitedAgents.map((art: any) => { const serviceId = art.alias ? `hypha-agents/${art.alias}` : undefined; return {