diff --git a/ee/app/assets/javascripts/ai/catalog/components/ai_catalog_flow_form.vue b/ee/app/assets/javascripts/ai/catalog/components/ai_catalog_flow_form.vue index 62818d377d67226a1b2803d754571f2dcae44b5e..e9db1faf5b8938ca3eeb8b6ab8a44bdf604be8bd 100644 --- a/ee/app/assets/javascripts/ai/catalog/components/ai_catalog_flow_form.vue +++ b/ee/app/assets/javascripts/ai/catalog/components/ai_catalog_flow_form.vue @@ -13,6 +13,8 @@ import { VISIBILITY_LEVEL_PRIVATE, VISIBILITY_LEVEL_PUBLIC, FLOW_VISIBILITY_LEVEL_DESCRIPTIONS, + DEFAULT_FLOW_YML_STRING, + DEFAULT_THIRD_PARTY_FLOW_YML_STRING, } from 'ee/ai/catalog/constants'; import { TYPENAME_PROJECT } from '~/graphql_shared/constants'; import { convertToGraphQLId } from '~/graphql_shared/utils'; @@ -29,6 +31,7 @@ import FormSection from './form_section.vue'; import VisibilityLevelRadioGroup from './visibility_level_radio_group.vue'; export default { + name: 'AiCatalogFlowForm', components: { ErrorsAlert, AiCatalogFormButtons, @@ -93,21 +96,33 @@ export default { type = AI_CATALOG_TYPE_THIRD_PARTY_FLOW; } - const isFlowType = type === AI_CATALOG_TYPE_FLOW; const { definition, ...initialValuesWithoutDefinition } = this.initialValues; + + const definitionFlow = + type === AI_CATALOG_TYPE_FLOW && definition ? definition : DEFAULT_FLOW_YML_STRING; + + const definitionThirdPartyFlow = + type === AI_CATALOG_TYPE_THIRD_PARTY_FLOW && definition + ? definition + : DEFAULT_THIRD_PARTY_FLOW_YML_STRING; + + const projectId = + !this.isGlobal && this.projectId + ? convertToGraphQLId(TYPENAME_PROJECT, this.projectId) + : this.initialValues.projectId; + + const visibilityLevel = this.initialValues.public + ? VISIBILITY_LEVEL_PUBLIC + : VISIBILITY_LEVEL_PRIVATE; + return { formValues: { ...initialValuesWithoutDefinition, type, - definitionFlow: isFlowType ? definition || '' : '', - definitionThirdPartyFlow: !isFlowType ? definition || '' : '', - projectId: - !this.isGlobal && this.projectId - ? convertToGraphQLId(TYPENAME_PROJECT, this.projectId) - : this.initialValues.projectId, - visibilityLevel: this.initialValues.public - ? VISIBILITY_LEVEL_PUBLIC - : VISIBILITY_LEVEL_PRIVATE, + definitionFlow, + definitionThirdPartyFlow, + projectId, + visibilityLevel, }, formErrors: [], }; @@ -258,7 +273,7 @@ export default { }, groupAttrs: { labelDescription: s__( - 'AICatalog|This YAML configuration file determines the prompts, tools, and capabilities of your flow. Required properties: version, environment, components, routers, flow, prompts.', + 'AICatalog|This YAML configuration file determines the prompts, tools, and capabilities of your flow. Required properties: version, environment, components, prompts, routers, flow.', ), }, }, diff --git a/ee/app/assets/javascripts/ai/catalog/constants.js b/ee/app/assets/javascripts/ai/catalog/constants.js index 1ec5b76d6c670400ed3db531ea7ef71c72de4d98..0ccfd30bb75f1ec4412d0122f54ec60abcd0f06d 100644 --- a/ee/app/assets/javascripts/ai/catalog/constants.js +++ b/ee/app/assets/javascripts/ai/catalog/constants.js @@ -114,3 +114,82 @@ export const FLOW_TYPE_APOLLO_CONFIG = { }, }, }; + +export const DEFAULT_FLOW_YML_STRING = `\ +# Schema version +version: "v1" +# Environment where the flow runs (ambient = GitLab's managed environment) +environment: ambient + +# Components define the steps in your flow +# Each component can be an Agent, DeterministicStep, or other component types +components: + - name: "my_agent" + type: AgentComponent # Options: AgentComponent, DeterministicStepComponent + prompt_id: "my_prompt" # References a prompt defined below + inputs: + - "context:goal" # Input from user or previous component + toolset: [] # Add tool names here: ["get_issue", "create_issue_note"] + + # Optional: Add UI logging for debugging + # ui_log_events: + # - "on_agent_final_answer" + # - "on_tool_execution_success" + +# Define your prompts here +# Each prompt configures an AI agent's behavior and model settings +prompts: + - prompt_id: "my_prompt" # Must match the prompt_id referenced above + name: "My Agent Prompt" + model: + params: + model_class_provider: anthropic # Provider: anthropic, openai, etc. + model: claude-sonnet-4-20250514 # Model identifier + max_tokens: 8192 # Adjust based on expected response length + + # System and user prompts define the agent's behavior + prompt_template: + system: | + You are GitLab Duo Chat, an agentic AI assistant. + Your role is to help users with their GitLab tasks. + Be concise, accurate, and actionable in your responses. + + # Add specific instructions for your use case here + + user: | + {{goal}} + + # Available variables depend on your inputs: + # {{goal}} - The user's request + # {{context}} - Additional context from previous steps + + placeholder: history # Maintains conversation context + + params: + timeout: 180 # Seconds before timeout + +# Routers define the flow between components +# Use "end" as the final destination +routers: + - from: "my_agent" + to: "end" + + # Example: Multi-step flow + # - from: "fetch_data" + # to: "process_data" + # - from: "process_data" + # to: "my_agent" + # - from: "my_agent" + # to: "end" + +# Define the entry point for your flow +flow: + entry_point: "my_agent" +`; + +export const DEFAULT_THIRD_PARTY_FLOW_YML_STRING = `\ +image: alpine:latest +injectGatewayToken: true +commands: + - echo "Hello, World!" +`; diff --git a/ee/spec/frontend/ai/catalog/components/ai_catalog_flow_form_spec.js b/ee/spec/frontend/ai/catalog/components/ai_catalog_flow_form_spec.js index d767be11a516259fbb542cc25c2a456b631c4504..f9d9c6efdcf06aff2b44db9413cdf569eb814aa7 100644 --- a/ee/spec/frontend/ai/catalog/components/ai_catalog_flow_form_spec.js +++ b/ee/spec/frontend/ai/catalog/components/ai_catalog_flow_form_spec.js @@ -6,7 +6,12 @@ import FormFlowType from 'ee/ai/catalog/components/form_flow_type.vue'; import FormProjectDropdown from 'ee/ai/catalog/components/form_project_dropdown.vue'; import VisibilityLevelRadioGroup from 'ee/ai/catalog/components/visibility_level_radio_group.vue'; import FormGroup from 'ee/ai/catalog/components/form_group.vue'; -import { VISIBILITY_LEVEL_PRIVATE, VISIBILITY_LEVEL_PUBLIC } from 'ee/ai/catalog/constants'; +import { + VISIBILITY_LEVEL_PRIVATE, + VISIBILITY_LEVEL_PUBLIC, + DEFAULT_FLOW_YML_STRING, + DEFAULT_THIRD_PARTY_FLOW_YML_STRING, +} from 'ee/ai/catalog/constants'; describe('AiCatalogFlowForm', () => { let wrapper; @@ -94,7 +99,7 @@ describe('AiCatalogFlowForm', () => { expect(findDescriptionField().props('value')).toBe(''); expect(findVisibilityLevelRadioGroup().props('initialValue')).toBe(false); expect(findVisibilityLevelRadioGroup().props('value')).toBe(VISIBILITY_LEVEL_PRIVATE); - expect(findDefinitionFlowField().props('value')).toBe(''); + expect(findDefinitionFlowField().props('value')).toBe(DEFAULT_FLOW_YML_STRING); expect(findDefinitionThirdPartyFlowField().exists()).toBe(false); }); @@ -107,7 +112,7 @@ describe('AiCatalogFlowForm', () => { expect(findDescriptionField().props('value')).toBe(''); expect(findVisibilityLevelRadioGroup().props('initialValue')).toBe(false); expect(findVisibilityLevelRadioGroup().props('value')).toBe(VISIBILITY_LEVEL_PRIVATE); - expect(findDefinitionFlowField().props('value')).toBe(''); + expect(findDefinitionFlowField().props('value')).toBe(DEFAULT_FLOW_YML_STRING); expect(findDefinitionThirdPartyFlowField().exists()).toBe(false); }); @@ -159,6 +164,22 @@ describe('AiCatalogFlowForm', () => { expect(findDefinitionThirdPartyFlowField().props('value')).toBe('third-party-definition'); expect(findDefinitionFlowField().exists()).toBe(false); }); + + it('renders default value when there was no definition set', () => { + createWrapper({ + props: { + initialValues: { + ...initialValues, + definition: '', + type: 'THIRD_PARTY_FLOW', + }, + }, + }); + + expect(findDefinitionThirdPartyFlowField().props('value')).toBe( + DEFAULT_THIRD_PARTY_FLOW_YML_STRING, + ); + }); }); }); diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 85d3182e4cdf6c34561ea521a9dd3b38ce198bee..f91faf1ddee2988697dd951374960f53e7fc08cf 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -2853,7 +2853,7 @@ msgstr "" msgid "AICatalog|This YAML configuration file determines the prompts, tools, and capabilities of your flow. Required properties: injectGatewayToken, image, commands" msgstr "" -msgid "AICatalog|This YAML configuration file determines the prompts, tools, and capabilities of your flow. Required properties: version, environment, components, routers, flow, prompts." +msgid "AICatalog|This YAML configuration file determines the prompts, tools, and capabilities of your flow. Required properties: version, environment, components, prompts, routers, flow." msgstr "" msgid "AICatalog|This agent can be made private if it is not used."