Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const Route = createFileRoute(
})

function RouteComponent() {
useDocumentTitle('Agentic workflow configuration')
useDocumentTitle('Agent task configuration')

return <AgenticWorkflowConfiguration />
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const Route = createFileRoute(
})

function RouteComponent() {
useDocumentTitle('Summary - Create agentic workflow')
useDocumentTitle('Summary - Create agent task')

return <AgenticWorkflowSummary />
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ import { eventsFactoryMock } from '@qovery/shared/factories'
import { type AuditLogsParams, DEFAULT_PAGE_SIZE } from '@qovery/shared/router'
import { ALL, type NavigationLevel, type SelectedItem, type TableFilterProps } from '@qovery/shared/ui'
import { useDocumentTitle, useSupportChat } from '@qovery/shared/util-hooks'
import { upperCaseFirstLetter } from '@qovery/shared/util-js'
import { AuditLogs } from '../audit-logs/audit-logs'
import { initializeSelectedItemsFromQueryParams } from '../utils/target-type-selection-utils'
import { getTargetTypeLabel, initializeSelectedItemsFromQueryParams } from '../utils/target-type-selection-utils'

const route = getRouteApi('/_authenticated/organization/$organizationId/audit-logs')

Expand Down Expand Up @@ -107,7 +106,7 @@ export function AuditLogsView() {

const organizationEventTargetTypes = Object.keys(OrganizationEventTargetType).map((item) => ({
value: item,
name: upperCaseFirstLetter(item).replace(/_/g, ' '),
name: getTargetTypeLabel(item),
}))

initializeSelectedItemsFromQueryParams(organizationId, organizationEventTargetTypes, 'target_type', urlParams)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ import {
type TableHeadProps,
} from '@qovery/shared/ui'
import { type SelectedTimestamps } from '@qovery/shared/ui'
import { upperCaseFirstLetter } from '@qovery/shared/util-js'
import FilterSection from '../filter-section/filter-section'
import RowEventFeature from '../row-event-feature/row-event-feature'
import {
computeDisplayByLabel,
computeMenusToDisplay,
computeSelectedItemsFromFilter,
getTargetTypeLabel,
} from '../utils/target-type-selection-utils'

export interface AuditLogsProps {
Expand Down Expand Up @@ -141,7 +141,7 @@ function createTableDataHead(
initialData: Object.keys(OrganizationEventTargetType).map((item) => {
return {
value: item,
name: upperCaseFirstLetter(item).replace(/_/g, ' '),
name: getTargetTypeLabel(item),

@cubic-dev-ai cubic-dev-ai Bot Aug 26, 2026

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.

P2: When AGENTIC_WORKFLOW is selected, this menu shows Agent task but the audit-log target-type badge still shows Agentic workflow. Reuse getTargetTypeLabel for the badge so the filter has one product name.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At libs/domains/audit-logs/feature/src/lib/audit-logs/audit-logs.tsx, line 144:

<comment>When `AGENTIC_WORKFLOW` is selected, this menu shows `Agent task` but the audit-log target-type badge still shows `Agentic workflow`. Reuse `getTargetTypeLabel` for the badge so the filter has one product name.</comment>

<file context>
@@ -141,7 +141,7 @@ function createTableDataHead(
           return {
             value: item,
-            name: upperCaseFirstLetter(item).replace(/_/g, ' '),
+            name: getTargetTypeLabel(item),
           }
         }),
</file context>
Fix with cubic

}
}),
initialSelectedItems: targetTypeSelectedItems,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { OrganizationEventTargetType } from 'qovery-typescript-axios'
import { type DecodedValueMap } from 'use-query-params'
import { type AuditLogsParams } from '@qovery/shared/router'
import { type SelectedItem } from '@qovery/shared/ui'
Expand Down Expand Up @@ -74,6 +75,30 @@ describe('FilterSection', () => {
screen.getByText(/Application/)
})

it('should render Agent task in target type and target badges', () => {
const queryParamsWithTarget = {
targetId: 'target-123',
targetType: OrganizationEventTargetType.AGENTIC_WORKFLOW,
}
const selectedItems: SelectedItem[] = [
{
filterKey: 'target_id',
item: { value: 'target-123', name: 'Review pull requests' },
},
]

renderWithProviders(
<FilterSection
{...props}
queryParams={queryParamsWithTarget as DecodedValueMap<AuditLogsParams>}
targetTypeSelectedItems={selectedItems}
/>
)

expect(screen.getByRole('button', { name: /Target Type: Agent task/ })).toBeInTheDocument()
expect(screen.getByRole('button', { name: /Agent task: Review pull requests/ })).toBeInTheDocument()
})

it('should render user badge when triggeredBy is set', () => {
const queryParamsWithTriggeredBy = {
triggeredBy: 'john_doe',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { type AuditLogsParams } from '@qovery/shared/router'
import { Button, Icon, type SelectedItem, type TableFilterProps, Truncate } from '@qovery/shared/ui'
import { dateYearMonthDayHourMinuteSecond } from '@qovery/shared/util-dates'
import { twMerge, upperCaseFirstLetter } from '@qovery/shared/util-js'
import { getTargetTypeLabel } from '../utils/target-type-selection-utils'

export interface CustomFilterProps {
clearFilter: () => void
Expand Down Expand Up @@ -55,7 +56,7 @@ function buildBadges(queryParams: AuditLogsParams, selectedItemsTargetType: Sele
badges.push({
key: 'target_type',
displayedName: 'Target Type',
value: upperCaseFirstLetter(queryParams.targetType).split('_').join(' '),
value: getTargetTypeLabel(queryParams.targetType),
isDeletable: true,
})
}
Expand Down Expand Up @@ -105,9 +106,7 @@ function buildBadges(queryParams: AuditLogsParams, selectedItemsTargetType: Sele
const selectedItem = selectedItemsTargetType.find((selectedItem) => selectedItem.filterKey === 'target_id')
if (selectedItem) {
const targetName = selectedItem?.item?.name ?? '...'
const targetType = upperCaseFirstLetter(queryParams.targetType ?? '...')
.split('_')
.join(' ')
const targetType = getTargetTypeLabel(queryParams.targetType ?? '...')
badges.push({
key: 'target_id',
displayedName: targetType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,20 @@ describe('RowEvent', () => {
expect(screen.getByText('unsupported-target')).not.toHaveAttribute('href')
})

it('should render Agent task for the agentic workflow target type', () => {
renderWithProviders(
<RowEvent
{...props}
event={{
...props.event,
target_type: OrganizationEventTargetType.AGENTIC_WORKFLOW,
}}
/>
)

expect(screen.getByText('Agent task')).toBeInTheDocument()
})

it.each([
[OrganizationEventTargetType.ORGANIZATION, '/organization/1/settings'],
[OrganizationEventTargetType.MEMBERS_AND_ROLES, '/organization/1/settings/members'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { IconEnum } from '@qovery/shared/enums'
import { CodeDiffEditor, CodeEditor, type DiffStats, Icon, Skeleton, Tooltip, Truncate } from '@qovery/shared/ui'
import { dateFullFormat, dateUTCString } from '@qovery/shared/util-dates'
import { twMerge, upperCaseFirstLetter } from '@qovery/shared/util-js'
import { getTargetTypeLabel } from '../utils/target-type-selection-utils'

export interface RowEventProps {
event: OrganizationEventResponse
Expand Down Expand Up @@ -312,7 +313,7 @@ export function RowEvent(props: RowEventProps) {
</div>
<div className="min-w-0 px-4 text-neutral-subtle">
<Skeleton height={10} width={80} show={isPlaceholder}>
<>{upperCaseFirstLetter(event.target_type ?? '')?.replace(/_/g, ' ')}</>
<>{getTargetTypeLabel(event.target_type ?? '')}</>
</Skeleton>
</div>
<div className="min-w-0 px-4">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { OrganizationEventApi, OrganizationEventTargetType } from 'qovery-typescript-axios'
import { type SelectedItem } from '@qovery/shared/ui'
import { computeMenusToDisplay } from './target-type-selection-utils'
import { computeMenusToDisplay, getTargetTypeLabel } from './target-type-selection-utils'

const mockGetOrganizationEventTargets = jest.spyOn(OrganizationEventApi.prototype, 'getOrganizationEventTargets')

const targetTypeItem: SelectedItem = {
filterKey: 'target_type',
item: {
value: OrganizationEventTargetType.AGENTIC_WORKFLOW,
name: 'Agentic workflow',
name: 'Agent task',
},
}

Expand Down Expand Up @@ -85,3 +85,13 @@ describe('computeMenusToDisplay', () => {
)
})
})

describe('getTargetTypeLabel', () => {
it('uses the Agent task product name for the agentic workflow API type', () => {
expect(getTargetTypeLabel(OrganizationEventTargetType.AGENTIC_WORKFLOW)).toBe('Agent task')
})

it('formats other API target types', () => {
expect(getTargetTypeLabel(OrganizationEventTargetType.CONTAINER_REGISTRY)).toBe('Container registry')
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
type NavigationLevel,
type SelectedItem,
} from '@qovery/shared/ui'
import { upperCaseFirstLetter } from '@qovery/shared/util-js'

const SERVICE_TARGET_TYPES: ReadonlySet<OrganizationEventTargetType> = new Set([
OrganizationEventTargetType.AGENTIC_WORKFLOW,
Expand All @@ -17,6 +18,12 @@ const SERVICE_TARGET_TYPES: ReadonlySet<OrganizationEventTargetType> = new Set([
OrganizationEventTargetType.TERRAFORM,
])

export function getTargetTypeLabel(targetType: string) {

@cubic-dev-ai cubic-dev-ai Bot Aug 26, 2026

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.

P2: The new getTargetTypeLabel helper is only wired into the two filter menus (audit-logs.tsx and audit-logs-view.tsx). Other audit-log surfaces that render the same API value still show "Agentic workflow": the active-filter badge in filter-section.tsx (value: upperCaseFirstLetter(queryParams.targetType).split('_').join(' ') at line 58, and again at line 108 for the target_id badge) and the Target type column in row-event.tsx (upperCaseFirstLetter(event.target_type ?? '')?.replace(/_/g, ' ') at line 315). After this change an AGENTIC_WORKFLOW look-up shows "Agent task" in the menu but "Agentic workflow" in the row and in the active-filter chip, so the rename the PR is meant to land is incomplete. Use getTargetTypeLabel at every site that formats target_type.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At libs/domains/audit-logs/feature/src/lib/utils/target-type-selection-utils.tsx, line 21:

<comment>The new `getTargetTypeLabel` helper is only wired into the two filter menus (audit-logs.tsx and audit-logs-view.tsx). Other audit-log surfaces that render the same API value still show "Agentic workflow": the active-filter badge in filter-section.tsx (`value: upperCaseFirstLetter(queryParams.targetType).split('_').join(' ')` at line 58, and again at line 108 for the target_id badge) and the Target type column in row-event.tsx (`upperCaseFirstLetter(event.target_type ?? '')?.replace(/_/g, ' ')` at line 315). After this change an AGENTIC_WORKFLOW look-up shows "Agent task" in the menu but "Agentic workflow" in the row and in the active-filter chip, so the rename the PR is meant to land is incomplete. Use `getTargetTypeLabel` at every site that formats `target_type`.</comment>

<file context>
@@ -17,6 +18,12 @@ const SERVICE_TARGET_TYPES: ReadonlySet<OrganizationEventTargetType> = new Set([
   OrganizationEventTargetType.TERRAFORM,
 ])
 
+export function getTargetTypeLabel(targetType: string) {
+  return targetType === OrganizationEventTargetType.AGENTIC_WORKFLOW
+    ? 'Agent task'
</file context>
Fix with cubic

return targetType === OrganizationEventTargetType.AGENTIC_WORKFLOW
? 'Agent task'
: upperCaseFirstLetter(targetType).replace(/_/g, ' ')
}

function getTargetTypeSelected(selectedItems: SelectedItem[]): OrganizationEventTargetType | undefined {
const selectedTargetType = selectedItems.find((selectedItem) => {
return selectedItem.filterKey === 'target_type'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,19 @@ interface FormValues {
}

const PAGE_CONTENT: Record<SettingsPage, { title: string; description: string }> = {
general: { title: 'General settings', description: 'Configure the workflow name, description, and availability.' },
general: { title: 'General settings', description: 'Configure the agent task name, description, and availability.' },
'ai-configuration': {
title: 'AI configuration',
description: 'Configure the model and instructions used by this workflow.',
description: 'Configure the model and instructions used by this agent task.',
},
connections: {
title: 'Connections',
description: 'Configure the Git repositories, MCP servers, and Dockerfile fragment available to the workflow.',
description: 'Configure the Git repositories, MCP servers, and Dockerfile fragment available to the agent task.',
},
outputs: { title: 'Outputs', description: 'Configure the webhooks called when the workflow produces an output.' },
outputs: { title: 'Outputs', description: 'Configure the webhooks called when the agent task produces an output.' },
governance: {
title: 'Governance',
description: 'Control the hosts and webhook source addresses allowed for this workflow.',
description: 'Control the hosts and webhook source addresses allowed for this agent task.',
},
}

Expand Down Expand Up @@ -241,7 +241,7 @@ export function AgenticWorkflowSettings({ page }: AgenticWorkflowSettingsProps)
name="name"
label="Name"
value={values.name}
error={!values.name.trim() ? 'Please enter a workflow name.' : undefined}
error={!values.name.trim() ? 'Please enter an agent task name.' : undefined}
onChange={(event) => form.setValue('name', event.currentTarget.value, { shouldDirty: true })}
/>
<InputTextArea
Expand All @@ -254,14 +254,14 @@ export function AgenticWorkflowSettings({ page }: AgenticWorkflowSettingsProps)
small
align="top"
value={values.enabled}
title="Enable workflow"
description="Allow this workflow to listen for and process incoming requests."
title="Enable agent task"
description="Allow this agent task to listen for and process incoming requests."
onChange={(value) => form.setValue('enabled', value, { shouldDirty: true })}
/>
<div className="pt-6">
<h2 className="mb-1 text-base font-medium text-neutral">Resources</h2>
<p className="mb-4 text-sm text-neutral-subtle">
Configure the compute resources allocated to the workflow.
Configure the compute resources allocated to the agent task.
</p>
<div className="grid gap-4 sm:grid-cols-2">
{(['cpu', 'ram', 'gpu', 'storage'] as const).map((name) => (
Expand Down Expand Up @@ -303,7 +303,7 @@ export function AgenticWorkflowSettings({ page }: AgenticWorkflowSettingsProps)
<div>
<h2 className="text-base font-medium text-neutral">Git repositories</h2>
<p className="mt-1 text-sm text-neutral-subtle">
Select the repositories and branches the workflow can access.
Select the repositories and branches the agent task can access.
</p>
</div>
<Button type="button" variant="outline" color="neutral" size="sm" onClick={addRepository}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ export function AgenticWorkflowServiceActions({
const deleteAgenticWorkflow = () => {
openModalConfirmation({
title: `Delete ${service.name}?`,
description:
'This will permanently delete the agentic workflow and its associated data. This action cannot be undone.',
description: 'This will permanently delete the agent task and its associated data. This action cannot be undone.',
name: service.name,
action: async () => {
await deleteService({ serviceId: service.id, serviceType: service.serviceType })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ describe('AgenticWorkflowServiceList', () => {
})
renderWithProviders(<AgenticWorkflowServiceList environment={environment} />)

expect(screen.getByRole('heading', { name: 'Agentic workflows' })).toBeInTheDocument()
expect(screen.getByRole('heading', { name: 'Agent tasks' })).toBeInTheDocument()
expect(screen.getByText('Review pull requests')).toBeInTheDocument()
expect(screen.getByText('Triage incidents')).toBeInTheDocument()
expect(screen.getByText('Enabled')).toBeInTheDocument()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ export function AgenticWorkflowServiceList({ environment }: AgenticWorkflowServi
<Section className="flex flex-col gap-3.5">
<div className="flex flex-col gap-1">
<Heading level={3} className="font-medium text-neutral-subtle">
Agentic workflows
Agent tasks
</Heading>
<p className="text-sm text-neutral-subtle">AI workflows triggered through webhooks and connected services.</p>
<p className="text-sm text-neutral-subtle">One-time tasks delegated to AI agents.</p>
</div>

<div className="flex flex-col overflow-hidden rounded-lg border border-neutral">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function useEditService({
if (payload.serviceType === 'AGENTIC_WORKFLOW') {
return {
title: 'Service updated',
description: 'Your agentic workflow settings were saved',
description: 'Your agent task settings were saved',
}
}
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,9 +321,9 @@ export function AgenticWorkflowConfiguration() {
<FunnelFlowBody customContentWidth="max-w-[620px]">
<Section>
<header className="mb-5">
<Heading level={1}>Create agentic workflow</Heading>
<Heading level={1}>Create agent task</Heading>
<p className="mt-1 text-sm leading-5 text-neutral-subtle">
Configure the inputs, tools, model, governance, and outputs used by your workflow.
Configure the inputs, tools, model, governance, and outputs used by your agent task.
</p>
</header>

Expand All @@ -338,7 +338,7 @@ export function AgenticWorkflowConfiguration() {
label="Name"
value={values.name}
autoFocus
error={showNameError ? 'Please enter a workflow name.' : undefined}
error={showNameError ? 'Please enter an agent task name.' : undefined}
onChange={(event) => form.setValue('name', event.currentTarget.value, { shouldDirty: true })}
/>
<InputTextArea
Expand Down Expand Up @@ -374,8 +374,8 @@ export function AgenticWorkflowConfiguration() {
small
align="top"
value={values.workflowEnabled}
title="Enable workflow"
description="Start listening and executing this workflow as soon as it is created."
title="Enable agent task"
description="Start listening and executing this agent task as soon as it is created."
onChange={(value) => form.setValue('workflowEnabled', value, { shouldDirty: true })}
/>
<ContinueButton disabled={!values.name.trim()} onClick={goToNextSection} />
Expand Down Expand Up @@ -708,7 +708,7 @@ export function AgenticWorkflowConfiguration() {
value={values.agentPrompt}
textareaClassName="min-h-40"
variableKeys={variableValues.map((variable) => variable.variable ?? '').filter(Boolean)}
hint="Describe the workflow behavior. Example: review incoming webhook payloads, open a pull request when needed, then notify the team."
hint="Describe the agent task behavior. Example: review incoming webhook payloads, open a pull request when needed, then notify the team."
onChange={(value) => form.setValue('agentPrompt', value, { shouldDirty: true })}
/>
<ContinueButton disabled={!values.agentPrompt.trim()} onClick={goToNextSection} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function AIModelCards() {
<img src="/assets/ai-tools/claude.svg" alt="" aria-hidden="true" className="h-5 w-5" />
Anthropic
</span>
<span className="text-xs text-neutral-subtle">Claude models used by the workflow agent.</span>
<span className="text-xs text-neutral-subtle">Claude models used by the agent task.</span>
</button>
<button
type="button"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,9 @@ export function AgenticWorkflowSummary() {
<FunnelFlowBody customContentWidth="max-w-[1024px]">
<Section className="space-y-10">
<div className="flex flex-col gap-2">
<Heading className="mb-2">Ready to create your agentic workflow</Heading>
<Heading className="mb-2">Ready to create your agent task</Heading>
<p className="text-sm text-neutral-subtle">
Review the workflow configuration before creating it. Webhook details will be generated after creation.
Review the agent task configuration before creating it. Webhook details will be generated after creation.
</p>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ describe('ServiceNew', () => {
expect(screen.getByText('Cron Job')).toBeInTheDocument()
expect(screen.getByText('Helm')).toBeInTheDocument()
expect(screen.getAllByText('Terraform').length).toBeGreaterThanOrEqual(1)
expect(screen.queryByText('Agentic workflow')).not.toBeInTheDocument()
expect(screen.queryByText('Agent task')).not.toBeInTheDocument()
})

it('should render agentic workflow entry when feature flag is enabled', () => {
Expand All @@ -141,8 +141,8 @@ describe('ServiceNew', () => {
<ServiceNew organizationId="org-1" projectId="project-1" environmentId="env-1" availableTemplates={[]} />
)

expect(screen.getByText('Agentic workflow')).toBeInTheDocument()
expect(screen.getByRole('link', { name: /Agentic workflow/i })).toHaveAttribute(
expect(screen.getByText('Agent task')).toBeInTheDocument()
expect(screen.getByRole('link', { name: /Agent task/i })).toHaveAttribute(
'href',
'/organization/org-1/project/project-1/environment/env-1/service/create/agentic-workflow'
)
Expand Down
Loading
Loading