Skip to content

feat(frontend): auto-open artifact panel when agent creates new artifact (SECRT-2263) - #12997

Merged
ntindle merged 8 commits into
devfrom
ntindle/secrt-2263-investigation
May 8, 2026
Merged

feat(frontend): auto-open artifact panel when agent creates new artifact (SECRT-2263)#12997
ntindle merged 8 commits into
devfrom
ntindle/secrt-2263-investigation

Conversation

@ntindle

@ntindle ntindle commented May 4, 2026

Copy link
Copy Markdown
Member

Why / What / How

Why: The artifact side panel never auto-opened when Autopilot generated a new artifact — users had to manually click the artifact card to see their result. This made the feature feel broken.

What: Implements card-based auto-open for the artifact panel. Each ArtifactCard registers itself on mount via the Zustand store, which decides whether to auto-open based on readiness, user-close suppression, and agent origin. Explicit user closes are respected: once the user dismisses the panel in a session, it won't auto-open again for that session (but resets naturally on session switch).

How:

  • Card-based registration: ArtifactCard calls registerArtifactForAutoOpen(ref) on mount — the store tracks known IDs and auto-opens only genuinely new agent artifacts
  • Module-level tracking: _autoOpenKnownIds, _autoOpenReady, _autoOpenUserClosed kept outside Zustand to avoid re-renders
  • Readiness gating: useAutoOpenArtifacts hook manages lifecycle — defers readiness until messages hydrate (prevents false opens on session load), gates on feature flag and session ID
  • User-close detection: isOpen true→false transition sets _autoOpenUserClosed, suppressing auto-open for the rest of the session
  • Metadata upgrade: When a richer ArtifactRef arrives for a known ID (e.g. file-part with real MIME replacing text-extracted null MIME), the active artifact is upgraded in-place
  • Streaming safety: UUID format validation in extractWorkspaceArtifacts rejects partial IDs during character-by-character streaming
  • clearCopilotLocalData reset: Module-level auto-open state is cleared alongside Zustand store state

Changes 🏗️

  • store.ts — Module-level auto-open tracking vars; 4 new store actions (registerArtifactForAutoOpen, setAutoOpenReady, markUserClosedForAutoOpen, resetAutoOpenState); removed isPreviewableArtifact gate from openArtifact; clearCopilotLocalData clears module-level state
  • ArtifactCard.tsxuseEffect calls registerArtifactForAutoOpen on mount; combined isOpen+activeID into derived isActive selector
  • useAutoOpenArtifacts.ts — Complete rewrite: lifecycle management only (session change reset, user-close detection, readiness gating, unmount cleanup)
  • helpers.ts — Hoisted FULL_UUID regex; UUID validation filter; reordered getMessageArtifacts to process file parts first with Map dedup
  • useAutoOpenArtifacts.test.ts — 15 tests across 2 describe blocks (hook lifecycle + store unit tests)
  • store.test.ts — Updated openArtifact test for removed previewability gate
  • ChatContainer.tsx — Updated hook call to pass messages, isLoadingSession, isArtifactsEnabled

Checklist 📋

For code changes:

  • I have clearly listed my changes in the PR description
  • I have made a test plan
  • I have tested my changes according to the test plan:
    • All 15 unit tests pass
    • 851 total tests pass
    • No auto-open on initial session load (pre-existing artifacts stay closed)
    • Auto-opens when agent produces a new artifact mid-session
    • Does not auto-open for user-uploaded files
    • Closing panel suppresses further auto-opens for that session
    • Switching sessions resets the suppression
    • clearCopilotLocalData properly resets auto-open state

- Extend useAutoOpenArtifacts with messages + isLoadingSession params
- Snapshot known artifact IDs on first stable render so history doesn't
  auto-open on session load
- Watch for new agent artifacts (origin === 'agent') and open the most
  recently added one automatically
- Track user-close via isOpen true→false transition; suppress auto-open
  for the remainder of that session (refs reset on session change via
  key={sessionId} remount)
- Update ChatContainer call site to pass messages and isLoadingSession
- Add 6 new tests: auto-open, no-open-on-load, no-open-user-upload,
  most-recent-wins, user-close-suppression, reconnect-no-false-positive
- Update __tests__ duplicate to use new hook signature

Closes SECRT-2263

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ntindle
ntindle requested a review from a team as a code owner May 4, 2026 16:37
@ntindle
ntindle requested review from Pwuts and kcze and removed request for a team May 4, 2026 16:37
@github-project-automation github-project-automation Bot moved this to 🆕 Needs initial review in AutoGPT development kanban May 4, 2026
@ntindle

ntindle commented May 4, 2026

Copy link
Copy Markdown
Member Author

/review

@github-actions github-actions Bot added the platform/frontend AutoGPT Platform - Front end label May 4, 2026
@autogpt-pr-reviewer

Copy link
Copy Markdown

Queued a review for PR #12997 at 7da0d33.

@github-actions github-actions Bot added the size/l label May 4, 2026
@coderabbitai

coderabbitai Bot commented May 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The PR enhances useAutoOpenArtifacts to intelligently auto-open artifact panels as new agent artifacts arrive in chat messages. The hook now accepts message list, loading state, and feature flag alongside session ID, detects when users manually close the panel to suppress further auto-opens, and opens the newest newly-created artifact when loading completes. ChatContainer wires the expanded interface, and comprehensive test coverage validates all scenarios.

Changes

Artifact Auto-Open

Layer / File(s) Summary
Hook Options & Signature
useAutoOpenArtifacts.ts
UseAutoOpenArtifactsOptions interface expands to include messages, isLoadingSession, and isArtifactsEnabled alongside existing sessionId. Hook parameters destructure all four.
Hook Logic & Lifecycle
useAutoOpenArtifacts.ts
Hook adds refs to detect user-initiated panel closures, resets panel on session change, snapshots agent artifact IDs on first stable render per session, detects newly-appearing artifacts, auto-opens the most recent when loading completes and feature is enabled, and cleans up panel state on unmount.
ChatContainer Integration
ChatContainer.tsx
Hook invocation updated to pass { sessionId, messages, isLoadingSession, isArtifactsEnabled } instead of { sessionId } only.
Test Setup & Scenarios
useAutoOpenArtifacts.test.ts
Adds typed UIMessage builders (makeAgentMessage, makeUserMessage) and defaultProps configuration. Validates: panel stays closed on same-session rerenders; resets on session/remount; auto-opens only for newly-arriving agent artifacts (not initial load or user artifacts); opens most-recent when multiple arrive; suppresses further opens after explicit user close until session change; ignores isLoadingSession pulses; and disabled when sessionId is null or isArtifactsEnabled is false.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • Significant-Gravitas/AutoGPT#12328: Modifies ChatContainer signature by adding pagination props, affecting the same component API as this PR's artifact auto-open context passing.

Suggested reviewers

  • Pwuts
  • kcze
  • Bentlybro

Poem

🐰 Artifacts bloom in every chat,
Auto-open like a friendly mat,
New panels spring when agents craft,
Unless the user clicks back.
Session shifts? The state's reset—
Smart behavior, truly blessed!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main feature addition: auto-opening the artifact panel when an agent creates a new artifact, with ticket reference.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The pull request description clearly explains the feature's motivation, implementation details, and comprehensive test coverage for the artifact panel auto-open functionality.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ntindle/secrt-2263-investigation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented May 4, 2026

Copy link
Copy Markdown
Contributor

🔍 PR Overlap Detection

This check compares your PR against all other open PRs targeting the same branch to detect potential merge conflicts early.

🟢 Low Risk — File Overlap Only

These PRs touch the same files but different sections (click to expand)

Summary: 0 conflict(s), 0 medium risk, 1 low risk (out of 1 PRs with file overlap)


Auto-generated on push. Ignores: openapi.json, lock files.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@autogpt_platform/frontend/src/app/`(platform)/copilot/components/ChatContainer/ChatContainer.tsx:
- Line 94: The call to useAutoOpenArtifacts should be skipped when the artifacts
feature flag is off to avoid populating hidden state; either wrap the call site
so useAutoOpenArtifacts({ sessionId, messages, isLoadingSession }) only runs
when Flag.ARTIFACTS is enabled, or modify useAutoOpenArtifacts itself to
early-return/no-op when the artifacts feature flag (Flag.ARTIFACTS) is disabled
(optionally clearing artifact panel state when the flag flips off). Ensure you
reference the existing hook name useAutoOpenArtifacts and the feature flag
Flag.ARTIFACTS so the change prevents any artifact-panel store updates while the
flag is false.

In
`@autogpt_platform/frontend/src/app/`(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.ts:
- Around line 58-85: The auto-open logic currently recomputes artifacts from the
entire messages array and treats any fetched historical artifacts as new; modify
useAutoOpenArtifacts to ignore prepended/historical messages by only inspecting
appended/tail-updated messages instead of the full messages list: keep a ref
like lastSeenMessageCountRef or lastSeenMessageIdsRef and when handling updates,
compute agentArtifacts only for messages.slice(lastSeenMessageCountRef.current)
(or filter messages by IDs greater than lastSeenMessageIdsRef), update that ref
after processing, and continue using existing refs (snapshotTakenRef,
knownArtifactIdsRef, userHasClosedRef) and functions (getMessageArtifacts,
openArtifact) so you only add and auto-open artifacts from newly appended
messages rather than the entire history.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1a3962c9-f0d4-4569-9e5f-cf1311931c48

📥 Commits

Reviewing files that changed from the base of the PR and between 2c840ea and 7da0d33.

📒 Files selected for processing (4)
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/__tests__/useAutoOpenArtifacts.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: lint
  • GitHub Check: integration_test
  • GitHub Check: check API types
  • GitHub Check: Cursor Bugbot
  • GitHub Check: end-to-end tests
  • GitHub Check: Check PR Status
  • GitHub Check: Analyze (typescript)
  • GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (16)
autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}: Use Node.js 21+ with pnpm package manager for frontend development
Always run 'pnpm format' for formatting and linting code in frontend development

Format frontend code using pnpm format

autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}: Fully capitalize acronyms in symbols, e.g. graphID, useBackendAPI
No linter suppressors (// @ts-ignore``, // eslint-disable) — fix the actual issue

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/__tests__/useAutoOpenArtifacts.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.test.ts
autogpt_platform/frontend/**/*.{tsx,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/frontend/**/*.{tsx,ts}: Use function declarations for components and handlers (not arrow functions) in React components
Only use arrow functions for small inline lambdas (map, filter, etc.) in React components
Use PascalCase for component names and camelCase with 'use' prefix for hook names in React
Use Tailwind CSS utilities only for styling in frontend components
Use design system components from 'src/components/' (atoms, molecules, organisms) in frontend development
Never use 'src/components/legacy/' in frontend code
Only use Phosphor Icons (@phosphor-icons/react) for icons in frontend components
Use generated API hooks from '@/app/api/generated/endpoints/' instead of deprecated 'BackendAPI' or 'src/lib/autogpt-server-api/
'
Use React Query for server state (via generated hooks) in frontend development
Default to client components ('use client') in Next.js; only use server components for SEO or extreme TTFB needs
Use '' component for rendering errors in frontend UI; use toast notifications for mutation errors; use 'Sentry.captureException()' for manual exceptions
Separate render logic from data/behavior in React components; keep comments minimal (code should be self-documenting)

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/__tests__/useAutoOpenArtifacts.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.test.ts
autogpt_platform/frontend/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/frontend/**/*.{ts,tsx}: No barrel files or 'index.ts' re-exports in frontend code
Regenerate API hooks with 'pnpm generate:api' after backend OpenAPI spec changes in frontend development

autogpt_platform/frontend/**/*.{ts,tsx}: Use function declarations (not arrow functions) for components/handlers
No any types unless the value genuinely can be anything
Keep render functions and hooks under ~50 lines; extract named helpers or sub-components when they grow longer

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/__tests__/useAutoOpenArtifacts.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.test.ts
autogpt_platform/frontend/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

autogpt_platform/frontend/src/**/*.{ts,tsx}: Use generated API hooks from @/app/api/__generated__/endpoints/ following the pattern use{Method}{Version}{OperationName}, and regenerate with pnpm generate:api
Separate render logic from business logic using component.tsx + useComponent.ts + helpers.ts pattern, colocate state when possible and avoid creating large components, use sub-components in local /components folder
Use function declarations for components and handlers, use arrow functions only for callbacks
Do not use useCallback or useMemo unless asked to optimise a given function

autogpt_platform/frontend/src/**/*.{ts,tsx}: Keep files under ~200 lines; extract sub-components or hooks into their own files when a file grows beyond this
Use generated API hooks from @/app/api/__generated__/endpoints/ with pattern use{Method}{Version}{OperationName}
Always import the -Icon-suffixed alias from @phosphor-icons/react (e.g. TrashIcon, PlusIcon, SquareIcon) — bare exports are deprecated
Do not use useCallback or useMemo unless asked to optimize a given function
Never use src/components/__legacy__/* — use design system components from src/components/

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/__tests__/useAutoOpenArtifacts.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.test.ts
autogpt_platform/frontend/**/*.{tsx,css}

📄 CodeRabbit inference engine (AGENTS.md)

Use Tailwind CSS only for styling, use design tokens, and use Phosphor Icons only

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
autogpt_platform/frontend/src/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Component props should use interface Props { ... } (not exported) unless the interface needs to be used outside the component

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
autogpt_platform/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never type with any, if no types available use unknown

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/__tests__/useAutoOpenArtifacts.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.test.ts
autogpt_platform/frontend/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)

autogpt_platform/frontend/**/*.{tsx,jsx}: No dark: Tailwind classes — the design system handles dark mode
Use Next.js <Link> for internal navigation — never raw <a> tags
Use Tailwind CSS only for styling with design tokens and Phosphor Icons only

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
autogpt_platform/frontend/src/**/components/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)

Put sub-components in local components/ folder; component props should be type Props = { ... } (not exported) unless used outside the component

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
autogpt_platform/frontend/src/**/components/**/*.{ts,tsx}

📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)

Structure components as ComponentName/ComponentName.tsx + useComponentName.ts + helpers.ts

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/__tests__/useAutoOpenArtifacts.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.test.ts
autogpt_platform/frontend/src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)

Avoid index and barrel files

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/__tests__/useAutoOpenArtifacts.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.test.ts
autogpt_platform/frontend/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

No barrel files or index.ts re-exports in the frontend

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/__tests__/useAutoOpenArtifacts.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.test.ts
autogpt_platform/frontend/src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Do not type hook returns, let Typescript infer as much as possible

autogpt_platform/frontend/src/**/*.ts: Extract component logic into custom hooks grouped by concern, not by component, with each hook in its own .ts file
Do not type hook returns; let TypeScript infer as much as possible

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/__tests__/useAutoOpenArtifacts.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.test.ts
autogpt_platform/frontend/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

autogpt_platform/frontend/**/*.{test,spec}.{ts,tsx}: Use Vitest + RTL + MSW for integration tests as the primary testing approach (~90%, page-level), use Playwright for E2E critical flows, and use Storybook for design system components
Run frontend integration tests with pnpm test:unit (Vitest + RTL + MSW)

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/__tests__/useAutoOpenArtifacts.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.test.ts
autogpt_platform/frontend/src/app/**/__tests__/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)

Write integration tests in __tests__/ next to page.tsx using Vitest + RTL + MSW for new pages/features

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/__tests__/useAutoOpenArtifacts.test.ts
autogpt_platform/frontend/src/**/__tests__/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)

Use Orval-generated MSW handlers from @/app/api/__generated__/endpoints/{tag}/{tag}.msw.ts for API mocking

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/__tests__/useAutoOpenArtifacts.test.ts
🧠 Learnings (10)
📚 Learning: 2026-02-27T10:45:49.499Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12213
File: autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunMCPTool/helpers.tsx:23-24
Timestamp: 2026-02-27T10:45:49.499Z
Learning: Prefer using generated OpenAPI types from '@/app/api/__generated__/' for payloads defined in openapi.json (e.g., MCPToolsDiscoveredResponse, MCPToolOutputResponse). Use inline TypeScript interfaces only for payloads that are SSE-stream-only and not exposed via OpenAPI. Apply this pattern to frontend tool components (e.g., RunMCPTool) and related areas where similar SSE/openapi-discrepancies occur; avoid re-implementing types when a generated type is available.

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
📚 Learning: 2026-03-24T02:05:04.672Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12526
File: autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx:0-0
Timestamp: 2026-03-24T02:05:04.672Z
Learning: When gating React component logic on a React Query result (e.g., hooks like `useQuery` / `useGetV2GetCopilotUsage`), prefer destructuring and checking `isSuccess` (or aliasing it to a meaningful boolean like `isSuccess: hasUsage`) instead of relying on `!isLoading`. Reason: `isLoading` can be `false` in error/idle states where `data` may still be `undefined`, while `isSuccess` indicates the query completed successfully and `data` is populated.

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
📚 Learning: 2026-03-24T02:23:31.305Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12526
File: autogpt_platform/frontend/src/app/(platform)/copilot/components/RateLimitResetDialog/RateLimitResetDialog.tsx:0-0
Timestamp: 2026-03-24T02:23:31.305Z
Learning: In the Copilot platform UI code, follow the established Orval hook `onError` error-handling convention: first explicitly detect/handle `ApiError`, then read `error.response?.detail` (if present) as the primary message; if not available, fall back to `error.message`; and finally fall back to a generic string message. This convention should be used for generated Orval hooks even if the custom Orval mutator already maps details into `ApiError.message`, to keep consistency across hooks/components (e.g., `useCronSchedulerDialog.ts`, `useRunGraph.ts`, and rate-limit/reset flows).

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/__tests__/useAutoOpenArtifacts.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.test.ts
📚 Learning: 2026-03-31T14:04:42.444Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12623
File: autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatInput/ChatInput.tsx:172-177
Timestamp: 2026-03-31T14:04:42.444Z
Learning: In the Copilot frontend components under autogpt_platform/frontend/src/app/(platform)/copilot/, Tailwind dark mode variants (e.g., `dark:*`) are intentional and should be allowed. Do not flag `dark:` utilities in these Copilot UI components as incorrect; they are used to ensure proper contrast and correct behavior in both light and dark themes.

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
📚 Learning: 2026-04-01T18:54:16.035Z
Learnt from: Bentlybro
Repo: Significant-Gravitas/AutoGPT PR: 12633
File: autogpt_platform/frontend/src/app/(platform)/library/components/AgentFilterMenu/AgentFilterMenu.tsx:3-10
Timestamp: 2026-04-01T18:54:16.035Z
Learning: In the frontend, the legacy Select component at `@/components/__legacy__/ui/select` is an intentional, codebase-wide visual-consistency pattern. During code reviews, do not flag or block PRs merely for continuing to use this legacy Select. If a migration to the newer design-system Select is desired, bundle it into a single dedicated cleanup/migration PR that updates all Select usages together (e.g., avoid piecemeal replacements).

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/__tests__/useAutoOpenArtifacts.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.test.ts
📚 Learning: 2026-04-07T09:24:16.582Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12686
File: autogpt_platform/frontend/src/app/(no-navbar)/onboarding/steps/__tests__/PainPointsStep.test.tsx:1-19
Timestamp: 2026-04-07T09:24:16.582Z
Learning: In Significant-Gravitas/AutoGPT’s `autogpt_platform/frontend` (Vite + `vitejs/plugin-react` with the automatic JSX transform), do not flag usages of React types/components (e.g., `React.ReactNode`) in `.ts`/`.tsx` files as missing `React` imports. Since the React namespace is made available by the project’s TS/Vite setup, an explicit `import React from 'react'` or `import type { ReactNode } ...` is not required; only treat it as missing if typechecking (e.g., `pnpm types`) would actually fail.

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/__tests__/useAutoOpenArtifacts.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.test.ts
📚 Learning: 2026-04-02T05:43:49.128Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12640
File: autogpt_platform/frontend/src/app/(no-navbar)/onboarding/steps/WelcomeStep.tsx:13-13
Timestamp: 2026-04-02T05:43:49.128Z
Learning: Do not flag `import { Question } from "phosphor-icons/react"` as an invalid import. `Question` is a valid named export from `phosphor-icons/react` (as reflected in the package’s generated `.d.ts` files and re-exports via `dist/index.d.ts`), so it should be treated as a supported named export during code reviews.

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/__tests__/useAutoOpenArtifacts.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/useAutoOpenArtifacts.test.ts
📚 Learning: 2026-04-13T13:11:07.445Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12764
File: autogpt_platform/frontend/src/app/(platform)/library/components/SitrepItem/SitrepItem.tsx:143-145
Timestamp: 2026-04-13T13:11:07.445Z
Learning: In `autogpt_platform/frontend`, do not flag direct interpolation of `executionID` UUID strings into URL query parameters (e.g., `activeItem=${executionID}` in JSX/Next links). If the value is a UUID string matching `[0-9a-f-]`, it contains no reserved URL characters, so additional `encodeURIComponent` or Next.js object-based `href` encoding is unnecessary. Only treat it as an encoding issue if the query-param value is not guaranteed to be UUID-formatted (i.e., may include characters outside `[0-9a-f-]`).

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
📚 Learning: 2026-04-15T22:49:06.896Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 11235
File: autogpt_platform/frontend/src/app/(platform)/admin/diagnostics/components/ExecutionsTable.tsx:0-0
Timestamp: 2026-04-15T22:49:06.896Z
Learning: In the AutoGPT frontend (React Query + toast/ErrorCard patterns), do not require `Sentry.captureException` in React Query mutation `catch` blocks. React Query handles error propagation for mutation paths, so follow the established pattern: show toast notifications for mutation errors and use `ErrorCard` for render/fetch errors. Only add `Sentry.captureException` for truly manual/unexpected exception paths that are outside React Query’s control (e.g., standalone async utilities or event handlers not wired through React Query).

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
📚 Learning: 2026-04-20T20:07:22.981Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 11235
File: autogpt_platform/frontend/src/app/(platform)/admin/diagnostics/__tests__/ExecutionsTable.test.tsx:27-76
Timestamp: 2026-04-20T20:07:22.981Z
Learning: In this codebase, Orval-generated API modules under `src/app/api/__generated__/` are not committed to git and must be generated via `pnpm generate:api` (requires a running backend). In integration tests, it’s acceptable—and expected—to stub generated hooks/modules by mocking them with `vi.mock("@/app/api/__generated__/endpoints/{tag}/{tag}")`. Do not treat `vi.mock` of these generated hook modules as a violation of the MSW handler guideline, since the corresponding MSW handlers cannot be imported at test time when generated files are absent.

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/__tests__/useAutoOpenArtifacts.test.ts

@codecov

codecov Bot commented May 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 75.71429% with 17 lines in your changes missing coverage. Please review.
✅ Project coverage is 69.61%. Comparing base (468013a) to head (10ce5a3).

Additional details and impacted files
@@            Coverage Diff             @@
##              dev   #12997      +/-   ##
==========================================
- Coverage   70.20%   69.61%   -0.60%     
==========================================
  Files        2175     2162      -13     
  Lines      162477   158835    -3642     
  Branches    16682    16446     -236     
==========================================
- Hits       114063   110566    -3497     
+ Misses      45087    45002      -85     
+ Partials     3327     3267      -60     
Flag Coverage Δ
platform-frontend 31.08% <75.36%> (+0.08%) ⬆️
platform-frontend-e2e 31.30% <38.23%> (-0.24%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
Platform Backend 78.81% <ø> (-0.48%) ⬇️
Platform Frontend 37.57% <75.71%> (-0.02%) ⬇️
AutoGPT Libs ∅ <ø> (∅)
Classic AutoGPT 28.43% <ø> (ø)
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@autogpt-pr-reviewer autogpt-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📋 Automated Review — PR #12997

PR #12997 — feat(frontend): auto-open artifact panel when agent creates new artifact (SECRT-2263)
Author: ntindle | Files: 4

🎯 Verdict: REQUEST_CHANGES

PR Description Quality

✅ Has Why + What + How — PR description explains the feature, lists edge cases handled, documents the snapshot-based approach, and includes a test plan checklist.

What This PR Does

When an AI agent creates a file artifact during a copilot chat session, the artifact panel now automatically opens to show it. Previously, users had to manually discover and open new artifacts. The hook snapshots existing artifacts on session load, watches for new agent-originated ones, and respects user preference if they explicitly close the panel.

Specialist Findings

🛡️ Security ✅ — No new attack surface. Artifact ID extraction uses strict hex-UUID regex, origin === "agent" filter prevents user-controlled triggering, and openArtifact only mutates local Zustand UI state. No new endpoints, auth changes, or dependencies.

🏗️ Architecture ⚠️ — Well-structured hook with proper separation of concerns, but has a design gap.
🟠 Feature flag bypass: useAutoOpenArtifacts runs unconditionally even when Flag.ARTIFACTS is off (ChatContainer.tsx:94), mutating store state with no visible panel. (Flagged by: architect, product, discussion — 3 specialists)
🟡 Five refs approaching complexity ceiling (useAutoOpenArtifacts.ts:25); a single state-object ref or reducer would be clearer.

Performance ⚠️ — The auto-open effect runs getMessageArtifacts() (regex parsing) on ALL messages every time messages changes. During streaming, this fires dozens of times per second as O(M×P). Acceptable for typical session sizes (<100 messages) but suboptimal.
🟡 Track last-checked index and only scan tail-appended messages (useAutoOpenArtifacts.ts:58).
🟡 Move userHasClosedRef check before the artifact scan to short-circuit earlier (useAutoOpenArtifacts.ts:72).

🧪 Testing ⚠️ — 15 tests across 2 files cover all core behaviors well. Missing a few edge cases.
🟡 No test for sessionId: null early-return path.
🟡 No test for session-switch resetting close suppression.

📖 Quality ✅ — Excellent inline comments explaining why each effect exists, with ticket references. Naming is clear and consistent. Minor DRY issue with repeated type casts in tests.

📦 Product ⚠️ — Core feature works as described. One-way close suppression (no resume after manual re-open) is a minor UX gap but acceptable for v1.

📬 Discussion ⚠️ — CI is broken. Both CodeRabbit and Cursor Bugbot flagged the feature-flag bypass independently with no author response. No human approvals yet.

🔎 QA ⚠️ — All 15 unit tests pass. API verified working end-to-end. Live UI testing blocked by unrelated subscription paywall in test environment.

🔴 Blockers

  1. TypeScript errors break CI (useAutoOpenArtifacts.test.ts:28,46) — content property does not exist on UIMessage<unknown, UIDataTypes, UITools>. The makeAgentMessage and makeUserMessage test helpers use an invalid property, failing the check API types CI check. (Flagged by: discussion — CI failure)

  2. Prettier formatting failures (__tests__/useAutoOpenArtifacts.test.ts, useAutoOpenArtifacts.test.ts) — Both test files fail lint CI. Run pnpm format before pushing. (Flagged by: discussion — CI failure)

🟠 Should Fix

  1. Feature flag not respected by auto-open hook (ChatContainer.tsx:94) — useAutoOpenArtifacts runs and calls openArtifact() even when Flag.ARTIFACTS is disabled. This leaves phantom store state (isOpen=true, activeArtifact populated) with no rendered panel. If the flag toggles mid-session, the panel appears unexpectedly. Fix: pass isArtifactsEnabled to the hook and early-return when false. (Flagged by: architect, product, discussion — 3 specialists + 2 bots)

  2. Duplicate test files (__tests__/useAutoOpenArtifacts.test.ts + useAutoOpenArtifacts.test.ts) — Two files test the same hook (3 tests vs 11 tests). Both run in CI, creating maintenance burden and divergence risk. Consolidate into the canonical colocated file. (Flagged by: architect, testing, quality — 3 specialists)

🟡 Nice to Have

  1. Incremental message scanning (useAutoOpenArtifacts.ts:58) — Track last-checked message index to avoid O(M×P) full-scan on every streaming token. (performance, architect)
  2. Pagination ghost-open risk (useAutoOpenArtifacts.ts:58) — If chat loads older history via scroll-up pagination, those old messages would introduce unseen IDs and could trigger false auto-open. (discussion)
  3. Reset close suppression on manual re-open (useAutoOpenArtifacts.ts:36) — Once user closes panel, auto-open is suppressed forever in that session, even after manually re-opening an artifact. (product)

🔵 Nits

  1. Repeated type cast (useAutoOpenArtifacts.test.ts:211,239,253,271) — Extract type Messages = UIMessage<unknown, UIDataTypes, UITools>[] alias to reduce noise.

QA Screenshots

Screenshot Description
copilot ready Copilot page loads correctly after login ✅
subscription blocked Subscription paywall blocks live artifact testing (environment issue, not PR) ⚠️

Human Review Needed

YES — Feature-flag interaction needs human judgment on the correct gating approach, and CI failures need verification after fix. No human approvals yet on a user-facing UX change.

Risk Assessment

Merge risk: LOW | Rollback: EASY

Frontend-only hook change with no backend, DB, or auth modifications. Worst case is the artifact panel opens unexpectedly; no data loss possible. Easy to revert.

CI Status

❌ 2/6 local checks failed (frontend lint, frontend typecheck). TypeScript errors in test helpers and Prettier formatting issues must be resolved.


@github-project-automation github-project-automation Bot moved this from 🆕 Needs initial review to 🚧 Needs work in AutoGPT development kanban May 4, 2026
UIMessage type from the ai SDK does not include a content property;
it uses parts[] exclusively. Remove the extra field to fix tsc.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add isArtifactsEnabled feature flag guard to useAutoOpenArtifacts
- Move userHasClosedRef check before artifact extraction (early exit)
- Delete duplicate __tests__/useAutoOpenArtifacts.test.ts file
- Add Messages type alias to reduce repeated casts
- Add test: session switch resets close-suppression
- Add test: sessionId null path
- Add test: feature flag disabled path
- Use defaultProps pattern for cleaner test setup

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot added the conflicts Automatically applied to PRs with merge conflicts label May 6, 2026
@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

This pull request has conflicts with the base branch, please resolve those so we can evaluate the pull request.

Keep our useAutoOpenArtifacts.test.ts (dev deleted the stub; we have the full test suite).
ChatContainer.tsx auto-merged cleanly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot removed the conflicts Automatically applied to PRs with merge conflicts label May 7, 2026
Replace message-scanning approach with card-based auto-open architecture:
- ArtifactCard registers on mount via registerArtifactForAutoOpen
- Store decides auto-open using module-level state (no extra re-renders)
- Hook manages lifecycle only (session change, readiness, user-close)
- UUID validation prevents partial-ID artifacts during streaming
- Derived isActive selector reduces ArtifactCard re-renders
- FULL_UUID regex hoisted to module scope per Vercel best practices

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot added size/xl and removed size/l labels May 8, 2026
@ntindle
ntindle requested review from 0ubbe and Abhi1992002 May 8, 2026 00:12
Comment thread autogpt_platform/frontend/src/app/(platform)/copilot/store.ts
…etadata upgrade deps

- Reset wasOpenRef.current on session change to prevent false user-close detection
- Add artifact.mimeType to ArtifactCard effect deps for metadata upgrade path

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 5cf2a48. Configure here.

Comment thread autogpt_platform/frontend/src/app/(platform)/copilot/store.ts
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ntindle

ntindle commented May 8, 2026

Copy link
Copy Markdown
Member Author

/dev-review

@autogpt-pr-reviewer-in-dev

Copy link
Copy Markdown

Queued a review for PR #12997 at 10ce5a3.

@github-project-automation github-project-automation Bot moved this from 🚧 Needs work to 👍🏼 Mergeable in AutoGPT development kanban May 8, 2026
@ntindle
ntindle added this pull request to the merge queue May 8, 2026
Merged via the queue into dev with commit 2cd7fa0 May 8, 2026
35 checks passed
@ntindle
ntindle deleted the ntindle/secrt-2263-investigation branch May 8, 2026 06:05
@github-project-automation github-project-automation Bot moved this to Done in Frontend May 8, 2026
@github-project-automation github-project-automation Bot moved this from 👍🏼 Mergeable to ✅ Done in AutoGPT development kanban May 8, 2026

@autogpt-pr-reviewer-in-dev autogpt-pr-reviewer-in-dev Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📋 Automated Review — PR #12997

PR #12997 — feat(frontend): auto-open artifact panel when agent creates new artifact (SECRT-2263)
Author: ntindle | Files: 7

🎯 Verdict: APPROVE

PR Description Quality

✅ Has Why + What + How — PR describes the problem (users didn't know artifacts existed because the panel didn't open), the solution (card-based registration auto-opens the panel for agent-created artifacts), and the architectural approach (Zustand store actions + dedicated hook replacing message-scanning).

What This PR Does

Previously, when an AI agent created an artifact during a copilot session, the artifact panel stayed closed — users had to manually discover and open it. This PR auto-opens the artifact panel when the agent creates a new artifact, while respecting user intent (if the user closes the panel, it stays closed for that session). The implementation replaces an expensive message-scanning approach with an O(1) card-based registration pattern, and adds UUID validation to prevent DOM churn during streaming.

Specialist Findings

🛡️ Security ✅ — Frontend-only changes with no new API endpoints, auth changes, or backend code. The origin field on ArtifactRef is trusted from the AI SDK's message.role, which is an acceptable trust boundary. UUID validation via FULL_UUID regex is a positive security addition preventing malformed IDs from triggering unexpected API calls.
🟡 Removed isPreviewableArtifact gate from openArtifact (store.ts:229) slightly widens the client-side attack surface for malicious MIME types — blast radius is limited to the preview renderer.

🏗️ Architecture ✅ — Card-based registration is a well-designed pattern. Zustand store actions follow existing conventions. Hook separation is clean.
🟠 clearCopilotLocalData (store.ts:375-377) duplicates the three module-level reset lines from resetAutoOpenState (store.ts:329-331) — a DRY violation that will cause bugs if a fourth variable is added. (Flagged by: architect, quality — 2)
🟠 wasEverLoadingRef (useAutoOpenArtifacts.ts:70) is never reset on session change, which could block auto-open readiness in a fresh empty session after navigating from a loaded session. (Flagged by: architect, product — 2)

Performance ✅ — Net improvement. Replaces O(n·m) message-scanning on every streaming tick with O(1) per-artifact-mount registration. Module-level state avoids Zustand re-render overhead. UUID validation prevents DOM churn during streaming.
🟡 isOpen subscription in useAutoOpenArtifacts.ts:33 causes ChatContainer re-renders on every panel toggle; could use useCopilotUIStore.subscribe imperatively instead.

🧪 Testing ⚠️ — 59 tests pass (15 new auto-open + 44 store). The hook and store action tests are solid and well-structured. However, helpers.ts changes have zero test coverage:
🟠 extractWorkspaceArtifacts UUID validation filter (helpers.ts:295) — a streaming safety feature with no tests. A regression would cause ArtifactCards to mount with garbage IDs. (Flagged by: testing — 1)
🟠 getMessageArtifacts rewrite (helpers.ts:322-351) — file-parts-first dedup logic with Map-based approach has no tests. No verification that file-part metadata wins over text-extracted metadata for the same ID. (Flagged by: testing — 1)
🟠 clearCopilotLocalData auto-open state clearing (store.ts:376) has no test. (Flagged by: testing — 1)

📖 Quality ✅ — Clean, well-documented code. JSDoc on useAutoOpenArtifacts explains the architecture clearly. Naming is descriptive.
🔵 Test comment at useAutoOpenArtifacts.test.ts:252 reads like debugging notes ("wait, resetAutoOpenState clears known IDs too") rather than documentation.

📦 Product ✅ — Solves a real UX pain point where artifacts felt broken because they required manual opening. Proper gating: only agent artifacts auto-open, user uploads don't, user-close is respected per-session, session switches reset state.
🟡 No focus management on auto-open — screen reader users won't know the panel appeared. Consider aria-live region.
🟡 Rapid artifact generation (3+ at once) causes visible panel content switching with no debounce.

📬 Discussion ✅ — All critical reviewer concerns addressed: feature flag bypass fixed in ce8398e, O(n·m) performance regression eliminated by rewrite. 34/36 CI checks pass (2 expected skips). PR was approved and merged.

🔎 QA ✅ — All 59 unit tests pass. Copilot streaming API verified end-to-end (session creation → streaming → tool execution). Negative auth tests confirm proper access control. Interactive browser testing of the artifact panel auto-open was blocked by a pre-existing subscription paywall in the dev environment — not a regression from this PR.

🟠 Should Fix

  1. DRY the reset logic (store.ts:375-377) — clearCopilotLocalData duplicates three module-level reset lines from resetAutoOpenState. Replace with get().resetAutoOpenState() to maintain a single source of truth. (Flagged by: architect, quality — 2)
  2. Reset wasEverLoadingRef on session change (useAutoOpenArtifacts.ts:55) — The ref retains stale true from a previous session, blocking readiness in a fresh empty session until messages arrive. Add wasEverLoadingRef.current = false in the session-change effect. (Flagged by: architect, product — 2)
  3. Add tests for UUID validation in extractWorkspaceArtifacts (helpers.ts:295) — This streaming safety feature has zero coverage. Add tests: partial UUID rejected, full UUID accepted. (Flagged by: testing — 1)
  4. Add tests for getMessageArtifacts rewrite (helpers.ts:322-351) — File-parts-first dedup logic, origin assignment ("agent" vs "user-upload"), and Map-based dedup are all untested. (Flagged by: testing — 1)
  5. Add test for clearCopilotLocalData auto-open reset (store.ts:376) — Verify that calling clearCopilotLocalData clears known IDs, readiness, and user-closed flags. (Flagged by: testing — 1)

🟡 Nice to Have

  1. Use imperative subscribe for isOpen watcher (useAutoOpenArtifacts.ts:33) — Eliminates unnecessary ChatContainer re-renders on panel toggle by using useCopilotUIStore.subscribe in an effect instead of a React selector. (performance)
  2. Verify ArtifactPanel handles non-previewable MIME types (store.ts:229) — The isPreviewableArtifact gate was intentionally removed; ensure the panel shows a graceful fallback (file info + download) for binary blobs. (security, product)
  3. Encapsulate module-level state (store.ts:159-161) — If more auto-open variables are added, wrap _autoOpenKnownIds, _autoOpenReady, _autoOpenUserClosed in a small class with a single reset() method. (architect)
  4. Add aria-live for auto-open (store.ts:327) — Announce panel appearance to screen readers when auto-open triggers. (product)

🔵 Nits

  1. Clean up debugging comment (useAutoOpenArtifacts.test.ts:252) — Replace "wait, resetAutoOpenState clears known IDs too" with a concise note like // resetAutoOpenState clears knownIds, so re-registration opens again.

QA Screenshots

Screenshot Description
Copilot page Copilot page loads successfully; subscription paywall blocks interactive testing (env limitation, not PR regression) ⚠️

Human Review Needed

YES — While security risk is low (frontend-only), the module-level mutable state pattern, removed previewability gate, and untested helper functions warrant a human glance to confirm the architectural trade-offs align with team preferences. The wasEverLoadingRef stale-state bug could affect real user sessions.

Risk Assessment

Merge risk: LOW | Rollback: EASY

Frontend-only changes to client-side Zustand state and React hooks. No backend, database, or auth changes. Feature is isolated to the copilot artifact panel. Rollback is a simple revert with no data migration concerns.

CI Status

⚠️ 2/6 local quality checks passed, 4/6 failed (frontend lint, typecheck, build, and both test suites failed due to environment setup issues — not PR regressions). Remote CI: 34/36 checks passing (2 expected skips: Vercel Agent Review, Chromatic).


artifactPanel: { ...state.artifactPanel, activeArtifact: ref },
}));
}
return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (security/trust boundary)

The origin field on ArtifactRef is trusted without independent validation. If any code path incorrectly sets origin: "agent" for user-uploaded content, it would bypass the auto-open suppression for user uploads.

Suggestion: Consider validating origin against the message role at registration time rather than trusting the caller, or add a comment documenting this trust assumption.

set((state) => {
if (!isPreviewableArtifact(ref)) return state;

const { activeArtifact, history: prevHistory } = state.artifactPanel;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (security/removed guard)

Removed isPreviewableArtifact gate from openArtifact — any artifact type (including binary blobs) can now open the preview panel. Ensure the artifact preview renderer handles unexpected MIME types safely.

Suggestion: Verify that the ArtifactPanel gracefully handles non-previewable MIME types without attempting unsafe rendering (e.g., executing scripts from blob content).

@@ -335,6 +373,9 @@ export const useCopilotUIStore = create<CopilotUIState>((set) => ({

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟡 medium (architect/DRY violation)

clearCopilotLocalData duplicates the three module-level reset lines from resetAutoOpenState. If a fourth variable is added, both sites must be updated independently.

Suggestion: Replace the three lines with get().resetAutoOpenState() to maintain a single source of truth for auto-open state cleanup.

const prevSessionIdRef = useRef(sessionId);
const wasOpenRef = useRef(false);
const wasEverLoadingRef = useRef(isLoadingSession);
const hasMessages = messages.length > 0;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟡 medium (architect/Stale ref on session change)

wasEverLoadingRef is set to true when isLoadingSession is true but never reset on session change. If a user navigates from a loading session to a fresh one that was never loading, the stale true value gates readiness until messages arrive unnecessarily.

Suggestion: Add wasEverLoadingRef.current = false; inside the session-change effect (around line 45) alongside the other resets.

// ── Card-based auto-open tracking ───────────────────────────────────
// Module-level state — not in Zustand to avoid unnecessary re-renders.
// ArtifactCard calls registerArtifactForAutoOpen on mount; the store
// decides whether to auto-open based on these flags.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (architect/Shadow state design)

Three module-level mutable variables (_autoOpenKnownIds, _autoOpenReady, _autoOpenUserClosed) form a shadow state system invisible to Zustand devtools. Acceptable for perf but increases cognitive overhead.

Suggestion: Consider encapsulating in a small AutoOpenState class with a single reset() method if more variables are added in the future.

};
}),

// ── Card-based auto-open actions ─────────────────────────────────

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (product/UX: rapid artifact switching)

If an agent creates multiple artifacts in quick succession, each card mount calls registerArtifactForAutoOpenopenArtifact, causing rapid panel content switching. The user sees the active artifact change multiple times in under a second.

Suggestion: Consider debouncing auto-open or only auto-opening the last artifact in a batch (e.g., via a short setTimeout that gets cleared on subsequent registrations).

// Mark auto-open as ready once the session is fully loaded.
//
// React fires child effects (ArtifactCard) before parent effects (this hook),
// so all existing cards have already called registerArtifactForAutoOpen by the

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (product/UX: stale loading ref)

wasEverLoadingRef is never reset on session change. If session A loaded (wasEverLoading=true), then session B starts fresh (isLoadingSession=false, messages=[]), the guard at line 81 blocks readiness until messages arrive — which may never happen in a brand-new empty session, preventing auto-open of the first agent artifact.

Suggestion: Reset wasEverLoadingRef.current = false in the session-change effect (around line 55) alongside the other resets.

artifactPanel: { ...state.artifactPanel, activeArtifact: ref },
}));
}
return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (product/Accessibility: focus management)

When openArtifact is called via auto-open, the panel appears but focus remains in the chat area. Screen reader users receive no notification that new content appeared.

Suggestion: Add an aria-live="polite" region to the artifact panel or programmatically announce the auto-open event.


const prevSessionIdRef = useRef(sessionId);
const wasOpenRef = useRef(false);
const wasEverLoadingRef = useRef(isLoadingSession);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (product/UX: close-detection coupling)

The user-close detection (isOpen true→false) fires for programmatic closes too (e.g., session-change resetArtifactPanel). It relies on the session-change effect running afterward to call resetAutoOpenState, clearing the false positive. This ordering dependency is implicit and fragile.

Suggestion: Guard the close-detection with a check like if (sessionId === prevSessionIdRef.current) so programmatic session-change resets don't trigger user-close suppression.

};
}),

// ── Card-based auto-open actions ─────────────────────────────────

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (discussion/coverage gap)

Codecov reports 17 lines missing coverage in this PR (75.71% patch). The registerArtifactForAutoOpen store action's metadata upgrade path and edge cases lack direct unit test coverage beyond the happy path.

Suggestion: Consider adding edge-case tests for the metadata upgrade logic (e.g. when active artifact is not the same ID as the registering ref).

itsababseh added a commit that referenced this pull request Jun 15, 2026
## AutoPilot Scheduling, New Design & Out of Beta

Changelog covering platform versions `v0.6.59` through `v0.6.63` (May 7
– June 10, 2026).

### Featured sections
- **AutoPilot major upgrades** — native scheduling (#13190),
self-distilled skills registry (#13195), message queuing (#12841)
- **New login & signup** — animated panel, aurora, integrations marquee
(#13169)
- **Subscriptions out of beta** — plans & payments fully live (#12935)
- **Settings rebuilt + profile dropdown** — cleaner layout, integrations
tab, quick-action menu (#13138, #12976)

### Improvements listed (not featured)
- Trigger On Anything (#12740)
- Export Chat as Markdown (#13070)
- Auto-open artifact panel (#12997)
- Slack block (#13008)
- Cost breakdown in briefing panel (#13129)
- Session sidebar pagination (#13128)
- Faster first response in AutoPilot (#12828)

### Files changed
- `docs/platform/changelog/may-7-june-10-2026.md` — new changelog page
- `docs/platform/.gitbook/assets/` — 5 new hero images
- `docs/platform/SUMMARY.md` — new entry at top
- `docs/platform/changelog/README.md` — new row at top of table
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

platform/frontend AutoGPT Platform - Front end size/xl

Projects

Status: ✅ Done
Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants