From 1976764abc48009980ddf8f8dfa1298012e9da38 Mon Sep 17 00:00:00 2001 From: Colin Smith <7762103+colinmxs@users.noreply.github.com> Date: Wed, 29 Apr 2026 16:31:38 -0600 Subject: [PATCH] Release 1.0.0-beta.23: Voice streaming, multi-agent architecture, AgentCore Identity connectors, E2E testing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Voice Mode — Bidirectional Audio Streaming: - VoiceAgent with Nova Sonic 2 via Strands BidiAgent - WebSocket endpoint at /voice/stream with JWT auth - Frontend voice overlay with AudioWorklet mic capture, gapless PCM playback, and state machine (idle → connecting → listening → speaking) - Voice-text continuity loads prior text session history into voice context - Accept-first WebSocket pattern aligned with AgentCore reference architecture Multi-Agent Architecture: - BaseAgent ABC → ChatAgent → MainAgent hierarchy with factory registry - create_agent(agent_type) routes requests at runtime (chat, skill, voice) - SkillAgent with three-level progressive skill disclosure (catalog → SKILL.md dispatch → tool execution) - Approval hooks for dangerous tool operations via BeforeToolCallEvent - Environment variables and magic strings centralized into config/constants.py External MCP Connectors via AgentCore Identity: - Replaces bespoke OAuth token vault (DynamoDB + KMS + Secrets Manager) with AgentCore Identity managed credential providers - AgentCoreContextMiddleware bridges Runtime headers into BedrockAgentCoreContext - oauth_required SSE event + frontend consent popup flow - Shared CfnWorkloadIdentity between app-api and inference-api for unified token vault keying - Admin UI rebranded from OAuth Providers to Connectors - Legacy OAuth service, token cache, encryption layer, and user routes deleted Per-Tool MCP Approval Gate: - MCPExternalApprovalHook driven by per-tool needs_approval flags in catalog - tool_approval_required SSE event with inline approve/decline prompt - Admin tool discovery endpoint for MCP server tool listing - PendingInterrupt rehydration on page refresh Tool Catalog Simplification: - DynamoDB as single source of truth; "Sync from Registry" removed - ToolAccessService sourced from TTL-cached DynamoDB snapshot - Bootstrap script seeds code-defined tools; admins add rest via form E2E Testing: - 3,400+ lines of Playwright specs across 12 test files - Cognito user provisioning for nightly runs (seed-e2e-users.sh) - Dynamic CloudFront URL discovery and callback URL registration Bug Fixes: - Duplicate sidebar entries from ensure_session_metadata_exists put_item race - OAuth2CallbackUrl query string rejected by middleware redirect-pivot guard - Workload identity service-linking preventing cross-service token minting - CloudFormation GetAtt on nested WorkloadIdentityDetails attribute - Delete-failed document state resilience UI: - Copy agent response button - Markdown links open in new tab (target="_blank", rel="noopener noreferrer") - ngx-markdown link security against reverse-tabnabbing Dependencies (Dependabot): - fastapi 0.135.3→0.136.1, uvicorn 0.44.0→0.46.0, boto3 1.42.83→1.42.96 - strands-agents 1.34.1→1.37.0, strands-agents-tools 0.3.0→0.5.1 - bedrock-agentcore 1.6.0→1.6.4, authlib 1.6.9→1.7.0 - openai 2.30.0→2.32.0, google-genai 1.70.0→1.73.1 - ruff 0.15.9→0.15.12, mypy 1.20.0→1.20.2, hypothesis 6.151.11→6.152.3 - trivy-action 0.35.0→0.36.0, actions/cache 5.0.4→5.0.5 - docker/build-push-action 7.0.0→7.1.0, actions/setup-node 6.3.0→6.4.0 252 files changed, 23,296 insertions(+), 7,999 deletions(-) --- .github/docs/NIGHTLY-BUILD.md | 37 +- .github/workflows/app-api.yml | 26 +- .github/workflows/codeql.yml | 4 +- .github/workflows/frontend.yml | 30 +- .github/workflows/gateway.yml | 18 +- .github/workflows/inference-api.yml | 26 +- .github/workflows/infrastructure.yml | 18 +- .github/workflows/nightly-deploy-pipeline.yml | 108 +- .github/workflows/nightly.yml | 76 +- .github/workflows/rag-ingestion.yml | 20 +- .github/workflows/sagemaker-fine-tuning.yml | 22 +- .github/workflows/version-check.yml | 2 +- .gitignore | 2 + .kiro/steering/e2e-testing.md | 269 +++++ CLAUDE.MD | 12 +- README.md | 8 +- RELEASE_NOTES.md | 306 +++++ VERSION | 2 +- backend/Dockerfile.inference-api | 4 +- backend/README.md | 6 +- backend/pyproject.toml | 37 +- backend/run-app-api.sh | 4 + backend/run-inference-api.sh | 4 + backend/scripts/seed_bootstrap_data.py | 37 + backend/scripts/test_voice_client.py | 125 ++ backend/src/.env.example | 15 +- backend/src/agents/local_tools/__init__.py | 3 - backend/src/agents/local_tools/weather.py | 120 -- backend/src/agents/main_agent/README.md | 6 +- .../src/agents/main_agent/USAGE_EXAMPLES.md | 16 +- backend/src/agents/main_agent/__init__.py | 22 +- backend/src/agents/main_agent/agent_types.py | 69 ++ backend/src/agents/main_agent/base_agent.py | 411 +++++++ backend/src/agents/main_agent/chat_agent.py | 94 ++ .../src/agents/main_agent/config/__init__.py | 9 + .../src/agents/main_agent/config/constants.py | 121 ++ .../agents/main_agent/core/agent_factory.py | 9 +- .../agents/main_agent/core/model_config.py | 22 +- .../integrations/external_mcp_client.py | 253 ++-- .../integrations/gateway_mcp_client.py | 3 +- .../integrations/oauth_token_cache.py | 51 + backend/src/agents/main_agent/main_agent.py | 329 +----- .../src/agents/main_agent/quota/repository.py | 5 +- .../main_agent/session/compaction_models.py | 10 +- .../main_agent/session/hooks/__init__.py | 9 +- .../main_agent/session/hooks/oauth_consent.py | 443 +++++++ .../main_agent/session/hooks/tool_approval.py | 117 ++ .../main_agent/session/memory_config.py | 6 +- .../session/preview_session_manager.py | 4 +- .../main_agent/session/session_factory.py | 5 +- .../session/turn_based_session_manager.py | 4 +- backend/src/agents/main_agent/skill_agent.py | 123 ++ .../src/agents/main_agent/skills/__init__.py | 24 + .../agents/main_agent/skills/decorators.py | 46 + .../definitions/canvas-morning-check/SKILL.md | 127 ++ .../skills/definitions/web-search/SKILL.md | 28 + .../main_agent/skills/skill_registry.py | 298 +++++ .../agents/main_agent/skills/skill_tools.py | 168 +++ .../streaming/stream_coordinator.py | 533 +++++---- .../main_agent/tools/oauth_tool_service.py | 334 ------ .../agents/main_agent/tools/tool_catalog.py | 11 +- .../agents/main_agent/tools/tool_filter.py | 7 +- backend/src/agents/main_agent/voice_agent.py | 403 +++++++ .../src/apis/app_api/admin/oauth/routes.py | 457 +++++--- .../app_api/admin/services/tool_access.py | 21 +- .../src/apis/app_api/admin/tools/routes.py | 137 ++- backend/src/apis/app_api/assistants/routes.py | 2 +- backend/src/apis/app_api/chat/routes.py | 2 +- .../src/apis/app_api/connectors/__init__.py | 0 backend/src/apis/app_api/connectors/routes.py | 432 +++++++ backend/src/apis/app_api/costs/aggregator.py | 8 +- backend/src/apis/app_api/main.py | 17 +- backend/src/apis/app_api/messages/models.py | 4 +- backend/src/apis/app_api/sessions/routes.py | 42 +- .../app_api/sessions/services/metadata.py | 16 +- backend/src/apis/app_api/tools/__init__.py | 2 - backend/src/apis/app_api/tools/freshness.py | 149 +++ backend/src/apis/app_api/tools/models.py | 152 ++- backend/src/apis/app_api/tools/service.py | 159 +-- backend/src/apis/inference_api/chat/models.py | 22 +- backend/src/apis/inference_api/chat/routes.py | 223 +++- .../src/apis/inference_api/chat/service.py | 184 +-- .../apis/inference_api/chat/voice_routes.py | 576 ++++++++++ backend/src/apis/inference_api/main.py | 18 + .../src/apis/shared/middleware/__init__.py | 0 .../shared/middleware/agentcore_context.py | 105 ++ backend/src/apis/shared/oauth/__init__.py | 62 +- .../apis/shared/oauth/agentcore_identity.py | 368 ++++++ .../apis/shared/oauth/agentcore_registrar.py | 386 +++++++ .../shared/oauth/disconnect_repository.py | 135 +++ backend/src/apis/shared/oauth/encryption.py | 138 --- backend/src/apis/shared/oauth/models.py | 379 +++--- .../apis/shared/oauth/provider_repository.py | 374 +----- backend/src/apis/shared/oauth/routes.py | 268 ----- backend/src/apis/shared/oauth/service.py | 664 ----------- backend/src/apis/shared/oauth/token_cache.py | 165 --- .../src/apis/shared/oauth/token_repository.py | 337 ------ backend/src/apis/shared/sessions/__init__.py | 6 + backend/src/apis/shared/sessions/messages.py | 82 +- backend/src/apis/shared/sessions/metadata.py | 518 ++++++++- backend/src/apis/shared/sessions/models.py | 112 +- .../src/apis/shared/tool_approval/__init__.py | 0 .../src/apis/shared/tool_approval/models.py | 45 + .../integrations/test_external_mcp_client.py | 248 +++- .../integrations/test_oauth_token_cache.py | 61 + .../session/test_oauth_consent_hook.py | 787 +++++++++++++ .../main_agent/session/test_tool_approval.py | 147 +++ .../agents/main_agent/skills/__init__.py | 0 .../agents/main_agent/skills/conftest.py | 91 ++ .../main_agent/skills/test_skill_registry.py | 141 +++ .../main_agent/skills/test_skill_tools.py | 116 ++ .../agents/main_agent/test_agent_types.py | 72 ++ .../agents/main_agent/test_voice_agent.py | 156 +++ .../agents/main_agent/test_voice_routes.py | 117 ++ .../main_agent/tools/test_tool_catalog.py | 12 +- .../admin/services/test_tool_access.py | 174 +++ .../apis/app_api/test_admin_oauth_rollback.py | 119 ++ .../apis/app_api/test_connectors_routes.py | 473 ++++++++ .../apis/app_api/tools/test_freshness.py | 179 +++ .../test_agentcore_context_middleware.py | 189 +++ .../shared/oauth/test_agentcore_identity.py | 278 +++++ backend/tests/routes/conftest.py | 24 + backend/tests/routes/test_inference.py | 10 +- backend/tests/routes/test_tools.py | 8 +- backend/tests/shared/conftest.py | 9 +- backend/tests/shared/test_conftest_smoke.py | 3 - backend/tests/shared/test_coverage_boost.py | 79 -- backend/tests/shared/test_models_and_utils.py | 35 +- .../shared/test_oauth_agentcore_registrar.py | 403 +++++++ .../test_oauth_disconnect_repository.py | 79 ++ backend/tests/shared/test_oauth_models.py | 54 + .../tests/shared/test_oauth_repos_extended.py | 198 ---- .../tests/shared/test_oauth_repositories.py | 152 +-- backend/tests/shared/test_oauth_service.py | 153 --- .../tests/shared/test_sessions_messages.py | 6 +- .../tests/shared/test_sessions_metadata.py | 442 +++++++ backend/tests/test_seed_system_admin_jwt.py | 32 +- backend/uv.lock | 526 +++++++-- docs/SSE_ERROR_MESSAGING.md | 13 + frontend/ai.client/.gitignore | 6 + .../e2e/assistants/assistants.user.spec.ts | 445 +++++++ frontend/ai.client/e2e/auth-admin.setup.ts | 46 + frontend/ai.client/e2e/auth-user.setup.ts | 46 + .../e2e/auth/admin-access.user.spec.ts | 14 + frontend/ai.client/e2e/auth/login.spec.ts | 183 +++ .../ai.client/e2e/auth/navigation.spec.ts | 32 + frontend/ai.client/e2e/auth/not-found.spec.ts | 28 + .../ai.client/e2e/home-page/chat.user.spec.ts | 236 ++++ .../e2e/home-page/error-handling.user.spec.ts | 56 + .../e2e/home-page/file-upload-ui.user.spec.ts | 67 ++ .../e2e/home-page/model-selector.user.spec.ts | 62 + .../e2e/home-page/settings-panel.user.spec.ts | 76 ++ .../e2e/manage-sessions.user.spec.ts | 75 ++ .../e2e/settings/appearance.user.spec.ts | 147 +++ .../settings/chat-preferences.user.spec.ts | 912 +++++++++++++++ .../e2e/settings/profile.user.spec.ts | 182 +++ .../ai.client/e2e/settings/usage.user.spec.ts | 115 ++ frontend/ai.client/e2e/tsconfig.json | 11 + frontend/ai.client/package-lock.json | 100 +- frontend/ai.client/package.json | 10 +- frontend/ai.client/playwright.ci.config.ts | 80 ++ frontend/ai.client/playwright.config.ts | 90 ++ .../public/audio/pcm-capture.worklet.js | 17 + .../ai.client/src/app/admin/admin.page.ts | 6 +- .../src/app/admin/connectors/index.ts | 9 + .../connectors/models/connector.model.ts | 234 ++++ .../connectors/pages/connector-form.page.ts | 1018 +++++++++++++++++ .../pages/connector-list.page.ts} | 186 +-- .../services/connectors.service.spec.ts} | 56 +- .../connectors/services/connectors.service.ts | 113 ++ .../admin/manage-models/model-form.page.ts | 2 +- .../src/app/admin/oauth-providers/index.ts | 9 - .../models/oauth-provider.model.ts | 186 --- .../pages/provider-form.page.ts | 751 ------------ .../services/oauth-providers.service.ts | 154 --- .../sync-result-dialog.component.ts | 223 ---- .../admin/tools/models/admin-tool.model.ts | 40 +- .../app/admin/tools/pages/tool-form.page.ts | 193 +++- .../app/admin/tools/pages/tool-list.page.ts | 64 +- .../tools/services/admin-tool.service.ts | 34 +- frontend/ai.client/src/app/app.config.ts | 21 +- frontend/ai.client/src/app/app.routes.ts | 34 +- .../services/preview-chat.service.ts | 1 + .../model-dropdown.component.ts | 4 +- .../model-settings/model-settings.html | 2 +- .../src/app/components/sidenav/sidenav.html | 2 +- .../app/oauth-complete/oauth-complete.page.ts | 371 ++++++ .../oauth-consent.service.spec.ts | 98 ++ .../oauth-consent/oauth-consent.service.ts | 542 +++++++++ .../tool-approval/tool-approval.service.ts | 143 +++ .../chat-container.component.html | 15 +- .../chat-container.component.ts | 10 + .../chat-input/chat-input.component.html | 34 + .../chat-input/chat-input.component.ts | 57 + .../components/assistant-message.component.ts | 56 +- .../components/message-actions.component.ts | 117 ++ .../message-metadata-badges.component.ts | 62 +- .../oauth-consent-prompt.component.ts | 304 +++++ .../tool-approval-prompt.component.ts | 320 ++++++ .../tool-rail/tool-rail.component.ts | 8 +- .../components/tool-rail/tool-rail.model.ts | 7 +- .../message-list/message-list.component.html | 22 +- .../message-list/message-list.component.ts | 49 +- .../session/components/voice-overlay/index.ts | 1 + .../voice-overlay/voice-overlay.component.css | 202 ++++ .../voice-overlay.component.html | 116 ++ .../voice-overlay/voice-overlay.component.ts | 48 + .../services/chat/chat-http.service.ts | 42 +- .../services/chat/chat-request.service.ts | 155 ++- .../services/chat/stream-parser.service.ts | 57 +- .../session/services/models/content-types.ts | 12 +- .../session/message-map.service.spec.ts | 47 +- .../services/session/message-map.service.ts | 112 +- .../services/session/session.service.spec.ts | 2 +- .../services/session/session.service.ts | 59 +- .../services/voice/audio-player.service.ts | 99 ++ .../services/voice/audio-recorder.service.ts | 142 +++ .../src/app/session/services/voice/index.ts | 5 + .../app/session/services/voice/pcm-utils.ts | 96 ++ .../services/voice/voice-chat.service.ts | 649 +++++++++++ .../session/services/voice/voice.config.ts | 49 + .../src/app/session/session.page.html | 1 + .../ai.client/src/app/session/session.page.ts | 73 +- .../settings/connections/connections.page.ts | 399 ------- .../src/app/settings/connections/index.ts | 3 - .../app/settings/connections/models/index.ts | 1 - .../models/oauth-connection.model.ts | 57 - .../services/connections.service.spec.ts | 81 -- .../services/connections.service.ts | 136 --- .../settings/connections/services/index.ts | 1 - .../connectors/models/user-connector.model.ts | 37 + .../services/user-connectors.service.ts | 112 ++ .../oauth-callback/oauth-callback.page.ts | 655 ----------- .../connections-settings.page.ts | 308 ----- .../connectors-settings.page.ts | 373 ++++++ .../src/app/settings/settings.page.ts | 2 +- .../src/app/settings/settings.routes.ts | 4 +- .../app/shared/utils/stream-parser/index.ts | 4 + .../utils/stream-parser/stream-parser-core.ts | 66 ++ .../stream-parser/stream-parser-types.ts | 37 +- .../ai.client/src/environments/environment.ts | 4 +- frontend/ai.client/tsconfig.json | 3 +- infrastructure/lib/app-api-stack.ts | 131 +++ infrastructure/lib/inference-api-stack.ts | 86 +- infrastructure/lib/infrastructure-stack.ts | 37 + infrastructure/package-lock.json | 4 +- infrastructure/package.json | 2 +- scripts/common/recover-stack.sh | 69 ++ scripts/nightly/e2e-test.sh | 491 ++++++++ scripts/nightly/seed-e2e-users.sh | 120 ++ scripts/stack-app-api/deploy.sh | 4 + scripts/stack-frontend/deploy-cdk.sh | 7 + scripts/stack-gateway/deploy.sh | 4 + scripts/stack-inference-api/deploy.sh | 4 + scripts/stack-infrastructure/deploy.sh | 4 + scripts/stack-rag-ingestion/deploy.sh | 4 + 256 files changed, 23614 insertions(+), 8010 deletions(-) create mode 100644 .kiro/steering/e2e-testing.md create mode 100755 backend/run-app-api.sh create mode 100755 backend/run-inference-api.sh create mode 100644 backend/scripts/test_voice_client.py delete mode 100644 backend/src/agents/local_tools/weather.py create mode 100644 backend/src/agents/main_agent/agent_types.py create mode 100644 backend/src/agents/main_agent/base_agent.py create mode 100644 backend/src/agents/main_agent/chat_agent.py create mode 100644 backend/src/agents/main_agent/config/__init__.py create mode 100644 backend/src/agents/main_agent/config/constants.py create mode 100644 backend/src/agents/main_agent/integrations/oauth_token_cache.py create mode 100644 backend/src/agents/main_agent/session/hooks/oauth_consent.py create mode 100644 backend/src/agents/main_agent/session/hooks/tool_approval.py create mode 100644 backend/src/agents/main_agent/skill_agent.py create mode 100644 backend/src/agents/main_agent/skills/__init__.py create mode 100644 backend/src/agents/main_agent/skills/decorators.py create mode 100644 backend/src/agents/main_agent/skills/definitions/canvas-morning-check/SKILL.md create mode 100644 backend/src/agents/main_agent/skills/definitions/web-search/SKILL.md create mode 100644 backend/src/agents/main_agent/skills/skill_registry.py create mode 100644 backend/src/agents/main_agent/skills/skill_tools.py delete mode 100644 backend/src/agents/main_agent/tools/oauth_tool_service.py create mode 100644 backend/src/agents/main_agent/voice_agent.py create mode 100644 backend/src/apis/app_api/connectors/__init__.py create mode 100644 backend/src/apis/app_api/connectors/routes.py create mode 100644 backend/src/apis/app_api/tools/freshness.py create mode 100644 backend/src/apis/inference_api/chat/voice_routes.py create mode 100644 backend/src/apis/shared/middleware/__init__.py create mode 100644 backend/src/apis/shared/middleware/agentcore_context.py create mode 100644 backend/src/apis/shared/oauth/agentcore_identity.py create mode 100644 backend/src/apis/shared/oauth/agentcore_registrar.py create mode 100644 backend/src/apis/shared/oauth/disconnect_repository.py delete mode 100644 backend/src/apis/shared/oauth/encryption.py delete mode 100644 backend/src/apis/shared/oauth/routes.py delete mode 100644 backend/src/apis/shared/oauth/service.py delete mode 100644 backend/src/apis/shared/oauth/token_cache.py delete mode 100644 backend/src/apis/shared/oauth/token_repository.py create mode 100644 backend/src/apis/shared/tool_approval/__init__.py create mode 100644 backend/src/apis/shared/tool_approval/models.py create mode 100644 backend/tests/agents/main_agent/integrations/test_oauth_token_cache.py create mode 100644 backend/tests/agents/main_agent/session/test_oauth_consent_hook.py create mode 100644 backend/tests/agents/main_agent/session/test_tool_approval.py create mode 100644 backend/tests/agents/main_agent/skills/__init__.py create mode 100644 backend/tests/agents/main_agent/skills/conftest.py create mode 100644 backend/tests/agents/main_agent/skills/test_skill_registry.py create mode 100644 backend/tests/agents/main_agent/skills/test_skill_tools.py create mode 100644 backend/tests/agents/main_agent/test_agent_types.py create mode 100644 backend/tests/agents/main_agent/test_voice_agent.py create mode 100644 backend/tests/agents/main_agent/test_voice_routes.py create mode 100644 backend/tests/apis/app_api/admin/services/test_tool_access.py create mode 100644 backend/tests/apis/app_api/test_admin_oauth_rollback.py create mode 100644 backend/tests/apis/app_api/test_connectors_routes.py create mode 100644 backend/tests/apis/app_api/tools/test_freshness.py create mode 100644 backend/tests/apis/shared/middleware/test_agentcore_context_middleware.py create mode 100644 backend/tests/apis/shared/oauth/test_agentcore_identity.py create mode 100644 backend/tests/shared/test_oauth_agentcore_registrar.py create mode 100644 backend/tests/shared/test_oauth_disconnect_repository.py create mode 100644 backend/tests/shared/test_oauth_models.py delete mode 100644 backend/tests/shared/test_oauth_repos_extended.py delete mode 100644 backend/tests/shared/test_oauth_service.py create mode 100644 frontend/ai.client/e2e/assistants/assistants.user.spec.ts create mode 100644 frontend/ai.client/e2e/auth-admin.setup.ts create mode 100644 frontend/ai.client/e2e/auth-user.setup.ts create mode 100644 frontend/ai.client/e2e/auth/admin-access.user.spec.ts create mode 100644 frontend/ai.client/e2e/auth/login.spec.ts create mode 100644 frontend/ai.client/e2e/auth/navigation.spec.ts create mode 100644 frontend/ai.client/e2e/auth/not-found.spec.ts create mode 100644 frontend/ai.client/e2e/home-page/chat.user.spec.ts create mode 100644 frontend/ai.client/e2e/home-page/error-handling.user.spec.ts create mode 100644 frontend/ai.client/e2e/home-page/file-upload-ui.user.spec.ts create mode 100644 frontend/ai.client/e2e/home-page/model-selector.user.spec.ts create mode 100644 frontend/ai.client/e2e/home-page/settings-panel.user.spec.ts create mode 100644 frontend/ai.client/e2e/manage-sessions.user.spec.ts create mode 100644 frontend/ai.client/e2e/settings/appearance.user.spec.ts create mode 100644 frontend/ai.client/e2e/settings/chat-preferences.user.spec.ts create mode 100644 frontend/ai.client/e2e/settings/profile.user.spec.ts create mode 100644 frontend/ai.client/e2e/settings/usage.user.spec.ts create mode 100644 frontend/ai.client/e2e/tsconfig.json create mode 100644 frontend/ai.client/playwright.ci.config.ts create mode 100644 frontend/ai.client/playwright.config.ts create mode 100644 frontend/ai.client/public/audio/pcm-capture.worklet.js create mode 100644 frontend/ai.client/src/app/admin/connectors/index.ts create mode 100644 frontend/ai.client/src/app/admin/connectors/models/connector.model.ts create mode 100644 frontend/ai.client/src/app/admin/connectors/pages/connector-form.page.ts rename frontend/ai.client/src/app/admin/{oauth-providers/pages/provider-list.page.ts => connectors/pages/connector-list.page.ts} (73%) rename frontend/ai.client/src/app/admin/{oauth-providers/services/oauth-providers.service.spec.ts => connectors/services/connectors.service.spec.ts} (59%) create mode 100644 frontend/ai.client/src/app/admin/connectors/services/connectors.service.ts delete mode 100644 frontend/ai.client/src/app/admin/oauth-providers/index.ts delete mode 100644 frontend/ai.client/src/app/admin/oauth-providers/models/oauth-provider.model.ts delete mode 100644 frontend/ai.client/src/app/admin/oauth-providers/pages/provider-form.page.ts delete mode 100644 frontend/ai.client/src/app/admin/oauth-providers/services/oauth-providers.service.ts delete mode 100644 frontend/ai.client/src/app/admin/tools/components/sync-result-dialog.component.ts create mode 100644 frontend/ai.client/src/app/oauth-complete/oauth-complete.page.ts create mode 100644 frontend/ai.client/src/app/services/oauth-consent/oauth-consent.service.spec.ts create mode 100644 frontend/ai.client/src/app/services/oauth-consent/oauth-consent.service.ts create mode 100644 frontend/ai.client/src/app/services/tool-approval/tool-approval.service.ts create mode 100644 frontend/ai.client/src/app/session/components/message-list/components/message-actions.component.ts create mode 100644 frontend/ai.client/src/app/session/components/message-list/components/oauth-consent-prompt/oauth-consent-prompt.component.ts create mode 100644 frontend/ai.client/src/app/session/components/message-list/components/tool-approval-prompt/tool-approval-prompt.component.ts create mode 100644 frontend/ai.client/src/app/session/components/voice-overlay/index.ts create mode 100644 frontend/ai.client/src/app/session/components/voice-overlay/voice-overlay.component.css create mode 100644 frontend/ai.client/src/app/session/components/voice-overlay/voice-overlay.component.html create mode 100644 frontend/ai.client/src/app/session/components/voice-overlay/voice-overlay.component.ts create mode 100644 frontend/ai.client/src/app/session/services/voice/audio-player.service.ts create mode 100644 frontend/ai.client/src/app/session/services/voice/audio-recorder.service.ts create mode 100644 frontend/ai.client/src/app/session/services/voice/index.ts create mode 100644 frontend/ai.client/src/app/session/services/voice/pcm-utils.ts create mode 100644 frontend/ai.client/src/app/session/services/voice/voice-chat.service.ts create mode 100644 frontend/ai.client/src/app/session/services/voice/voice.config.ts delete mode 100644 frontend/ai.client/src/app/settings/connections/connections.page.ts delete mode 100644 frontend/ai.client/src/app/settings/connections/index.ts delete mode 100644 frontend/ai.client/src/app/settings/connections/models/index.ts delete mode 100644 frontend/ai.client/src/app/settings/connections/models/oauth-connection.model.ts delete mode 100644 frontend/ai.client/src/app/settings/connections/services/connections.service.spec.ts delete mode 100644 frontend/ai.client/src/app/settings/connections/services/connections.service.ts delete mode 100644 frontend/ai.client/src/app/settings/connections/services/index.ts create mode 100644 frontend/ai.client/src/app/settings/connectors/models/user-connector.model.ts create mode 100644 frontend/ai.client/src/app/settings/connectors/services/user-connectors.service.ts delete mode 100644 frontend/ai.client/src/app/settings/oauth-callback/oauth-callback.page.ts delete mode 100644 frontend/ai.client/src/app/settings/pages/connections-settings/connections-settings.page.ts create mode 100644 frontend/ai.client/src/app/settings/pages/connectors-settings/connectors-settings.page.ts create mode 100644 scripts/common/recover-stack.sh create mode 100755 scripts/nightly/e2e-test.sh create mode 100644 scripts/nightly/seed-e2e-users.sh diff --git a/.github/docs/NIGHTLY-BUILD.md b/.github/docs/NIGHTLY-BUILD.md index 519a918af..2e7e0cd90 100644 --- a/.github/docs/NIGHTLY-BUILD.md +++ b/.github/docs/NIGHTLY-BUILD.md @@ -17,8 +17,9 @@ Tracks are specified as a comma-separated string in the `NIGHTLY_TRACKS` repo va | `test-backend-` | Run backend tests against `` | | `test-frontend-` | Run frontend tests against `` | | `deploy-` | Deploy full stack from `` with automatic teardown | +| `e2e-` | Deploy full stack from ``, run Playwright E2E tests, then teardown | | `merge-validation::` | Deploy ``, then overlay `` on top (colons delimit to avoid branch name ambiguity) | -| `all` | Run all tracks with defaults: tests + deploy on `develop`, MV `main`→`develop` | +| `all` | Run all tracks with defaults: tests + deploy + e2e on `develop`, MV `main`→`develop` | ### Examples @@ -27,9 +28,10 @@ test-backend-develop test-frontend-main,test-backend-main deploy-develop deploy-main,deploy-develop +e2e-develop merge-validation:main:develop merge-validation:main:feature/my-branch -test-backend-develop,deploy-develop,merge-validation:main:develop +test-backend-develop,deploy-develop,e2e-develop,merge-validation:main:develop all ``` @@ -44,7 +46,7 @@ The `resolve-tracks` job parses the tracks string into boolean flags and branch ## Workflow Jobs ### resolve-tracks -Parses the tracks string and outputs boolean flags (`run_test_backend`, `run_test_frontend`, `run_deploy`, `run_mv`) and branch refs for each enabled track. +Parses the tracks string and outputs boolean flags (`run_test_backend`, `run_test_frontend`, `run_deploy`, `run_e2e`, `run_mv`) and branch refs for each enabled track. ### Test Tracks @@ -62,7 +64,23 @@ When `deploy-` is specified, calls the reusable `nightly-deploy-pipeline - `alb-subdomain`: `nightly--api` - Automatic teardown (unless `skip_teardown` is set) -The deploy pipeline runs: install-infra → check-stack-deps → deploy-infra → deploy-rag → deploy-inference → deploy-app → deploy-frontend + deploy-gateway → smoke-test → teardown. +The deploy pipeline runs: install-infra → check-stack-deps → deploy-infra → deploy-rag → deploy-inference → deploy-app → deploy-frontend + deploy-gateway → smoke-test → e2e-tests (if enabled) → teardown. + +### E2E Test Track + +When `e2e-` is specified, calls the reusable `nightly-deploy-pipeline.yml` with: +- `project-prefix`: `nightly-e2e-` +- `alb-subdomain`: `nightly-e2e--api` +- `run-e2e`: `true` +- Automatic teardown (unless `skip_teardown` is set) + +This deploys a full stack and runs Playwright E2E tests against it. The E2E job runs after the smoke test confirms the stack is healthy. It uses a separate CI Playwright config (`playwright.ci.config.ts`) that points at the deployed stack URL instead of starting local servers. + +E2E test failures are **informational** — they mark the nightly summary as "partial" rather than "failed". This allows the track to stabilize without blocking other tracks. + +**Required secrets** (in the `development` environment): +- `E2E_ADMIN_USERNAME` / `E2E_ADMIN_PASSWORD` — Cognito admin test account +- `E2E_USER_USERNAME` / `E2E_USER_PASSWORD` — Cognito regular user test account ### Merge Validation Track @@ -91,6 +109,7 @@ Reusable workflow (`workflow_call`) containing the full deploy pipeline. | `skip-teardown` | no | Skip teardown (default: `false`) | | `label` | no | Label for job names | | `source-project-prefix` | no | If set, Docker jobs try ECR image promotion before building | +| `run-e2e` | no | Run Playwright E2E tests after smoke test (default: `false`) | ### Promote-or-Build Pattern @@ -126,6 +145,8 @@ Deploy and MV tracks use the `development` GitHub environment with overrides: ### Required Secrets - `AWS_ROLE_ARN` or `AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY` - `GITHUB_TOKEN` (automatically provided) +- `E2E_ADMIN_USERNAME` / `E2E_ADMIN_PASSWORD` — Cognito admin test account (required for e2e track) +- `E2E_USER_USERNAME` / `E2E_USER_PASSWORD` — Cognito regular user test account (required for e2e track) ### Required Variables - `AWS_REGION`, `CDK_AWS_ACCOUNT` @@ -138,6 +159,7 @@ Deploy and MV tracks use the `development` GitHub environment with overrides: | `backend-coverage` | 30 days | Backend test track enabled | | `frontend-coverage` | 30 days | Frontend test track enabled | | `coverage-comparison` | 30 days | Any test track succeeded | +| `playwright-report-