Skip to content

Conversation

@killiancolla
Copy link
Collaborator

@killiancolla killiancolla commented Nov 21, 2025

What does this PR do?

This PR integrates the Copilot configuration panel with the following features:

  • New tab in the admin configuration panel (protected by feature flag)
  • Ability to accept Copilot terms of use
  • Option to enable/disable Copilot
  • Toggle between read-only and read-write modes in configuration settings
  • Organization-wide list of recurring tasks with pause/resume and delete capabilities
  • Per-thread read-write mode switching (when enabled in config)
  • Disabled state for fields when Copilot is not activated

PR Checklist

  • This PR introduces breaking change(s) and has been labeled as such
  • This PR introduces new store changes
  • I made sure the code is type safe (no any)

@RemiBonnet
Copy link
Member

Qovery Preview

Qovery can create a Preview Environment for this PR.
To trigger its creation, please post a comment with one of the following command.

Command Blueprint environment
/qovery preview cc1de7de-94e5-40f8-8e45-bc8986d9dfec storybook
/qovery preview 28c47145-c8e7-4b9d-8d9e-c65c95b48425 staging
/qovery preview {all|UUID1,UUID2,...} To preview multiple environments

This comment has been generated from Qovery AI 🤖.
Below, a word from its wisdom :

Write comments that add new information that doesn’t exist in the code

@codecov
Copy link

codecov bot commented Nov 21, 2025

Codecov Report

❌ Patch coverage is 63.68564% with 134 lines in your changes missing coverage. Please review.
✅ Project coverage is 48.04%. Comparing base (6f95072) to head (e053144).

Files with missing lines Patch % Lines
...s/use-message-submission/use-message-submission.ts 52.45% 29 Missing ⚠️
.../lib/devops-copilot-panel/devops-copilot-panel.tsx 0.00% 25 Missing ⚠️
...ai-copilot-config/use-update-ai-copilot-config.tsx 11.76% 15 Missing ⚠️
...rc/lib/ai-copilot-settings/ai-copilot-settings.tsx 54.54% 8 Missing and 2 partials ⚠️
...ure/src/lib/devops-copilot-panel/submit-message.ts 33.33% 7 Missing and 3 partials ⚠️
...ot/feature/src/lib/mermaid-chart/mermaid-chart.tsx 0.00% 9 Missing ⚠️
...configuration/section-ai-copilot-configuration.tsx 72.72% 5 Missing and 1 partial ⚠️
.../devops-render-markdown/devops-render-markdown.tsx 0.00% 4 Missing ⚠️
...ring-task/use-delete-ai-copilot-recurring-task.tsx 33.33% 4 Missing ⚠️
...ring-task/use-toggle-ai-copilot-recurring-task.tsx 33.33% 4 Missing ⚠️
... and 10 more
Additional details and impacted files
@@             Coverage Diff             @@
##           staging    #2156      +/-   ##
===========================================
- Coverage    48.68%   48.04%   -0.64%     
===========================================
  Files         1161     1204      +43     
  Lines        20226    21235    +1009     
  Branches      6000     6235     +235     
===========================================
+ Hits          9847    10203     +356     
- Misses        8489     9122     +633     
- Partials      1890     1910      +20     
Flag Coverage Δ
unittests 48.04% <63.68%> (-0.64%) ⬇️

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

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@killiancolla
Copy link
Collaborator Author

/qovery preview all

@RemiBonnet
Copy link
Member

Qovery Preview

Preview environments were automatically created via Qovery.
Click on the links below to follow their deployments and use them.
👉 [PR] storybook - feat(devops-copilot): add copilot configuration panel - 2025-11-21T15:56:03Z
👉 [PR] staging - feat(devops-copilot): add copilot configuration panel - 2025-11-21T15:56:03Z

Another comment will be posted when deployments are finished

@RemiBonnet
Copy link
Member

Qovery Preview

Your preview environment failed to be deployed !
Click on the link below to check the deployment logs.
👉 [PR] storybook - feat(devops-copilot): add copilot configuration panel - 2025-11-21T15:56:03Z

@RemiBonnet
Copy link
Member

Qovery Preview

Your preview environment has been successfully deployed !
Click on the link below to open your service:
👉 console

@killiancolla killiancolla marked this pull request as ready for review November 26, 2025 10:24
Copy link
Member

@RemiBonnet RemiBonnet left a comment

Choose a reason for hiding this comment

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

Thanks @killiancolla 🙏

Here are my comments on the PR.
Next time, could you please add a short explanation of how and where we can test it? Since we don’t have the full context of your task, this information is necessary to review it properly

Also, please be careful with AI-generated code. You are responsible for any code you include, so make sure to test it and verify its performance. That part is not the reviewers’ job

You can check the codebase documentation in .cursor or in AGENT.md, and I’m happy to jump on a call if you need a clearer explanation of the codebase

  • The devops-copilot-panelcomponent is too large and contains too many lines. We need to refactor it and split it into smaller parts

  • You need to add some unit tests to cover your code

  • The loader is too big and not consistent with what we use elsewhere in the codebase. Please take inspiration from other settings pages. Also, the loading time is quite long, can we optimise it?

Image
  • The design isn't correct and ISO with other element, could you validate it with a designer? (cc: @TheoGrandin74 )
    • We don't have this color in the code base for "disable" btn
    • We should probably use BlockContent instead of a custom block to stay consistent with other settings pages
    • The Read-Write mode should be a Callout component this one is custom
Image

},
}),
recurringTasks: ({ organizationId }: { organizationId: string }) => ({
queryKey: [organizationId, 'recurring-tasks'],
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
queryKey: [organizationId, 'recurring-tasks'],
queryKey: [organizationId],

It is not necessary to add recurring-tasks it's already add by default

{isFeatureFlagPanel && !isCopilotEnabled && (
<>
<br></br>
<br></br>
Copy link
Member

Choose a reason for hiding this comment

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

The margins should be done with CSS not br

throw new Error('Organization ID is required but not provided in context')
}

// First, create a new thread
Copy link
Member

Choose a reason for hiding this comment

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

Remove this useless comment please 🙏
Try do keep only necessary comment when it's generate by IA !

@@ -0,0 +1,13 @@
import { render } from '__tests__/utils/setup-jest'
Copy link
Member

Choose a reason for hiding this comment

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

This one is deprecated you need to use import { renderWithProviders } from '@qovery/shared/util-tests'

@@ -0,0 +1,9 @@
import { render } from '__tests__/utils/setup-jest'
Copy link
Member

Choose a reason for hiding this comment

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

This one is deprecated

Suggested change
import { render } from '__tests__/utils/setup-jest'
import { renderWithProviders } from '@qovery/shared/util-tests'

last_error?: string
}

export function PageOrganizationAICopilot(props: PageOrganizationAICopilotProps) {
Copy link
Member

Choose a reason for hiding this comment

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

All this page should be renamed and inside the copilot library like AICopilotSettings

Copy link
Member

Choose a reason for hiding this comment

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

@killiancolla It’s not exactly what I expected, the whole setting page can be inside your domain and you can renamed it something like AICopilotSettings, with the section inside if you prefer.
Let me know if anything is unclear! 🙏


queryClient.setQueryData(
devopsCopilot.config({ organizationId: organization?.id ?? '' }).queryKey,
(old: any) => ({
Copy link
Member

Choose a reason for hiding this comment

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

You can't use any

{isEnabled && (
<div className="space-y-4 rounded border border-neutral-250 bg-neutral-100 p-6">
<div className="space-y-2">
<label className="text-sm font-medium text-neutral-400">Access Mode</label>
Copy link
Member

Choose a reason for hiding this comment

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

This one should be a Heading ?

<div>
<p className="mb-1 font-medium text-neutral-400">1. Data Collection and Usage</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut
Copy link
Member

Choose a reason for hiding this comment

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

Could you add real text? We can't merge lorem ipsum in production

@killiancolla
Copy link
Collaborator Author

Thanks @RemiBonnet for the detailed feedback 🙏
Sorry for the extra work this caused, I'll fix these things to have a cleaner code base on my side

…gn feedback

- separate sections with dedicated BlockContent and Section components
- reduce LoaderSpinner size
- replace custom information section with Callout "sky" component
- add confirmation modals for "Disable" and "Delete" task actions
- update "Disable" button styling (color change, icon removal)
- replace "Pause"/"Resume" and status badge with InputToggle component
- replace "Delete" button with icon button and update color
- align tasks list styling with codebase patterns
…ality

- Split PageOrganizationAICopilot into smaller components (OptIn, Configuration, ScheduledTasks)
- Replace deprecated test import
- Replace <br> tags with CSS margin classes
- Use Link component and URL constants
- Add useRecurringTasks and useConfig hook
- Remove useless comments, condition and parameters
- Rename feature flag variable: isFeatureFlagPanel -> isDevopsCopilotPanelFeatureFlag
- Extract mutations into custom hooks (useToggleRecurringTask, useDeleteRecurringTask, useUpdateOrgConfig)
- Use react-hook-form for T&C acceptance
- Use Icon component with iconName prop instead of name prop
- Remove width and height props from Icon components
@killiancolla
Copy link
Collaborator Author

killiancolla commented Dec 5, 2025

Hey @RemiBonnet,

I've addressed your comments, here's the changes I've made:

Refactoring

  • Split PageOrganizationAICopilot into smaller components (OptIn, Configuration, ScheduledTasks)
  • Extracted all queries and mutations into custom hooks (useRecurringTasks, useConfig, useToggleRecurringTask, useDeleteRecurringTask, useUpdateOrgConfig)
  • Renamed feature flag variable to isDevopsCopilotPanelFeatureFlag to avoid conflicts
  • Removed all 'any' types with proper typing from the API
  • Extracted devops-copilot-panel into smaller components (Header, Input, AssistantMessage, StreamingMessage, StreamingMermaidRenderer)
  • Created devops-copilot-panel.types.ts for centralized type definitions

UI/UX improvements

  • Reduced loader size
  • Replaced custom blocks with BlockContent components
  • Replaced custom information section with Callout "sky" component
  • Updated design after validation with Théo (button colors, spacing, layout)
  • Added confirmation modals for "Disable" and "Delete" task actions
  • Replaced Icon 'name' prop with 'iconName'
  • Removed width/height props from Icon components

Code quality

  • Replaced all <br> tags with CSS margin classes
  • Used Link component with URL constants (SETTINGS_AI_COPILOT_URL)
  • Implemented react-hook-form for T&C acceptance
  • Replaced deprecated test imports with renderWithProviders
  • Removed all unnecessary comments
  • Removed unnecessary conditions and parameters
  • Updated Terms & Conditions with real content
  • Added an environment variable for the Copilot backend URL

Testing

  • Added unit tests for hooks, components and utilities

You can test it all by navigating to the configuration panel for the Qovery Realm organization here. Don’t hesitate to tell me if you have some feedback or question!

last_error?: string
}

export function PageOrganizationAICopilot(props: PageOrganizationAICopilotProps) {
Copy link
Member

Choose a reason for hiding this comment

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

@killiancolla It’s not exactly what I expected, the whole setting page can be inside your domain and you can renamed it something like AICopilotSettings, with the section inside if you prefer.
Let me know if anything is unclear! 🙏

Copy link
Member

@RemiBonnet RemiBonnet left a comment

Choose a reason for hiding this comment

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

Well done, it's much better than before, I added a few comments, and it should be nice now!

import { renderHook } from '@qovery/shared/util-tests'
import { useAICopilotRecurringTasks } from './use-ai-copilot-recurring-tasks'

jest.mock('@tanstack/react-query', () => ({
Copy link
Member

Choose a reason for hiding this comment

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

The tests with react-query for hooks aren't necessary, you can remove it (for other hook as well)

import { useAuth0 } from '@auth0/auth0-react'
import { useEffect, useState } from 'react'
import { type Thread } from '../../devops-copilot-panel/devops-copilot-panel'
import { type Thread } from '../../devops-copilot-panel/devops-copilot-panel.types'
Copy link
Member

Choose a reason for hiding this comment

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

necessary?

@@ -0,0 +1,8 @@
export { DevopsCopilotPanel } from './devops-copilot-panel'
Copy link
Member

@RemiBonnet RemiBonnet Dec 8, 2025

Choose a reason for hiding this comment

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

Theses export aren't really necessary here, could you export directly from the files ?

import SectionScheduledTasks from './section-scheduled-tasks/section-scheduled-tasks'

export interface AICopilotSettingsProps {
organization?: Organization
Copy link
Member

@RemiBonnet RemiBonnet Dec 8, 2025

Choose a reason for hiding this comment

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

should be required no?

Copy link
Member

@RemiBonnet RemiBonnet left a comment

Choose a reason for hiding this comment

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

LGTM 👍

export function useAICopilotRecurringTasks({ organizationId }: UseAICopilotRecurringTasksProps) {
return useQuery({
...devopsCopilot.recurringTasks({ organizationId }),
enabled: !!organizationId,
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
enabled: !!organizationId,

Useless if organizationId is required

- Extract modal content
- Replace mermaidRenderCache logic with useMemo
- Memoize string processing logic
@killiancolla killiancolla requested a review from rmnbrd December 10, 2025 12:48
@killiancolla killiancolla requested a review from rmnbrd December 16, 2025 09:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants