diff --git a/js/console/src/components/workbenches/workbench/create-edit/WorkbenchCreateOrEdit.tsx b/js/console/src/components/workbenches/workbench/create-edit/WorkbenchCreateOrEdit.tsx
index 596f3622d3..7822db9bbb 100644
--- a/js/console/src/components/workbenches/workbench/create-edit/WorkbenchCreateOrEdit.tsx
+++ b/js/console/src/components/workbenches/workbench/create-edit/WorkbenchCreateOrEdit.tsx
@@ -588,7 +588,8 @@ function sanitizeInitialForm({
readBindings,
writeBindings,
}: WorkbenchFragment): WorkbenchFormState {
- const { infrastructure, coding, observability } = configuration ?? {}
+ const { infrastructure, coding, observability, selfService } =
+ configuration ?? {}
const { kubernetes, services, stacks, podLogs, vulnerabilities } =
infrastructure ?? {}
const { logs, metrics } = observability ?? {}
@@ -628,6 +629,7 @@ function sanitizeInitialForm({
repositoryId: repository?.id ?? null,
overrideBotUser: false,
configuration: {
+ selfService: selfService ?? false,
infrastructure: {
kubernetes,
services,
diff --git a/js/console/src/components/workbenches/workbench/create-edit/WorkbenchFormSteps.tsx b/js/console/src/components/workbenches/workbench/create-edit/WorkbenchFormSteps.tsx
index 91e6f3a04b..c85d51c4c1 100644
--- a/js/console/src/components/workbenches/workbench/create-edit/WorkbenchFormSteps.tsx
+++ b/js/console/src/components/workbenches/workbench/create-edit/WorkbenchFormSteps.tsx
@@ -128,6 +128,7 @@ export function WorkbenchSetupStep({
}: WorkbenchFormStepProps) {
const theme = useTheme()
const update = createFormUpdater(setFormState)
+ const selfService = formState.configuration?.selfService
const infra = formState.configuration?.infrastructure
const observability = formState.configuration?.observability
const capabilityCheckboxGridCss = {
@@ -172,6 +173,31 @@ export function WorkbenchSetupStep({
direction="column"
gap="large"
>
+
+
+
+ Enable Plural catalog and PR automation workflows for repeatable
+ GitOps provisioning. Prefer this for clear golden paths; undefined
+ or custom code changes still go through the coding agent.
+
+
+
+ update((d) => {
+ d.configuration ??= {}
+ d.configuration.selfService = checked
+ })
+ }
+ />
+
+
+
;
/** observability capabilities */
observability?: Maybe;
+ /** self-service subagent capability enabled */
+ selfService?: Maybe;
};
export type WorkbenchConfigurationAttributes = {
@@ -16901,6 +16903,8 @@ export type WorkbenchConfigurationAttributes = {
infrastructure?: InputMaybe;
/** observability capabilities (logs, metrics) */
observability?: InputMaybe;
+ /** enable the self-service subagent for catalog and PR automation workflows */
+ selfService?: InputMaybe;
};
export type WorkbenchConnection = {
@@ -17523,6 +17527,7 @@ export enum WorkbenchJobActivityType {
Observability = 'OBSERVABILITY',
Plan = 'PLAN',
Search = 'SEARCH',
+ SelfService = 'SELF_SERVICE',
Skill = 'SKILL',
Ticketing = 'TICKETING',
User = 'USER',
@@ -18037,6 +18042,7 @@ export enum WorkbenchSkillSubagent {
Observability = 'OBSERVABILITY',
Orchestrator = 'ORCHESTRATOR',
Search = 'SEARCH',
+ SelfService = 'SELF_SERVICE',
Skill = 'SKILL'
}
@@ -22848,7 +22854,7 @@ export type IssueWebhookTinyFragment = { __typename?: 'IssueWebhook', id: string
export type WorkbenchWebhookTinyFragment = { __typename?: 'WorkbenchWebhook', id: string, name?: string | null, priority?: number | null, webhook?: { __typename?: 'ObservabilityWebhook', id: string, type: ObservabilityWebhookType } | null, issueWebhook?: { __typename?: 'IssueWebhook', id: string, provider: IssueWebhookProvider } | null };
-export type WorkbenchFragment = { __typename?: 'Workbench', systemPrompt?: string | null, id: string, name: string, description?: string | null, agentRuntime?: { __typename?: 'AgentRuntime', id: string, name: string, allowedRepositories?: Array | null, type: AgentRuntimeType } | null, repository?: { __typename?: 'GitRepository', id: string } | null, configuration?: { __typename?: 'WorkbenchConfiguration', infrastructure?: { __typename?: 'WorkbenchInfrastructure', services?: boolean | null, stacks?: boolean | null, kubernetes?: boolean | null, podLogs?: boolean | null, vulnerabilities?: boolean | null, sentinels?: boolean | null } | null, observability?: { __typename?: 'WorkbenchObservability', logs?: boolean | null, metrics?: boolean | null } | null, coding?: { __typename?: 'WorkbenchCoding', mode?: AgentRunMode | null, repositories?: Array | null, enableBabysitting?: boolean | null } | null } | null, modes?: { __typename?: 'WorkbenchJobModes', plan?: boolean | null, verification?: boolean | null, model?: { __typename?: 'WorkbenchJobModel', provider?: AiProvider | null, model?: string | null } | null, coding?: { __typename?: 'WorkbenchJobCodingModes', approval?: boolean | null, babysit?: boolean | null, review?: boolean | null } | null, budget?: { __typename?: 'WorkbenchJobBudget', cost?: number | null, tokens?: number | null } | null, kubernetes?: { __typename?: 'WorkbenchJobKubernetesModes', update?: boolean | null, delete?: boolean | null, exec?: boolean | null, drain?: boolean | null, excludeNamespaces?: Array | null, requireNamespaces?: Array | null } | null } | null, budget?: { __typename?: 'WorkbenchBudget', enabled?: boolean | null, maximum?: number | null, minFree?: number | null, unit?: WorkbenchBudgetUnit | null, last?: number | null, lastUpdated?: string | null } | null, skills?: { __typename?: 'WorkbenchSkills', files?: Array | null, ref?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, workbenchSkills?: { __typename?: 'WorkbenchSkillConnection', edges?: Array<{ __typename?: 'WorkbenchSkillEdge', node?: { __typename?: 'WorkbenchSkill', id: string, name?: string | null, description?: string | null, contents?: string | null, subagents?: Array | null } | null } | null> | null } | null, workbenchKnowledge?: { __typename?: 'WorkbenchKnowledgeConnection', edges?: Array<{ __typename?: 'WorkbenchKnowledgeEdge', node?: { __typename?: 'WorkbenchKnowledge', id: string, name?: string | null, description?: string | null, knowledge?: string | null, labels?: Array | null, usages?: number | null, lastUsedAt?: string | null } | null } | null> | null } | null, tools?: Array<{ __typename?: 'WorkbenchTool', id: string, name: string, tool: WorkbenchToolType, categories?: Array | null, approval?: boolean | null, scmConnection?: { __typename?: 'ScmConnection', id: string, name: string, type: ScmType } | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, configuration?: { __typename?: 'WorkbenchToolConfiguration', http?: { __typename?: 'WorkbenchToolHttpConfiguration', url?: string | null, method?: string | null, body?: string | null, inputSchema?: Record | null, headers?: Array<{ __typename?: 'WorkbenchToolHttpHeader', name?: string | null, value?: string | null } | null> | null } | null, datadog?: { __typename?: 'WorkbenchToolDatadogConnection', site?: string | null } | null, elastic?: { __typename?: 'WorkbenchToolElasticConnection', index: string, url: string, username: string } | null, opensearch?: { __typename?: 'WorkbenchToolOpensearchConnection', host: string, index: string, awsAccessKeyId?: string | null, awsRegion?: string | null, assumeRoleArn?: string | null, usePodIdentity?: boolean | null } | null, loki?: { __typename?: 'WorkbenchToolLokiConnection', url?: string | null, username?: string | null, tenantId?: string | null } | null, victoriaLogs?: { __typename?: 'WorkbenchToolVictoriaLogsConnection', url?: string | null, username?: string | null, accountId?: string | null, projectId?: string | null } | null, prometheus?: { __typename?: 'WorkbenchToolPrometheusConnection', url?: string | null, username?: string | null, tenantId?: string | null, awsSigv4?: boolean | null, awsAccessKeyId?: string | null, awsRegion?: string | null } | null, tempo?: { __typename?: 'WorkbenchToolTempoConnection', url?: string | null, username?: string | null, tenantId?: string | null } | null, jaeger?: { __typename?: 'WorkbenchToolJaegerConnection', url?: string | null, username?: string | null } | null, atlassian?: { __typename?: 'WorkbenchToolAtlassianConnection', email?: string | null, url: string } | null, jira?: { __typename?: 'WorkbenchToolJiraConnection', email: string, url: string } | null, jiraDatacenter?: { __typename?: 'WorkbenchToolJiraDatacenterConnection', url: string } | null, linear?: { __typename?: 'WorkbenchToolLinearConnection', url: string } | null, slack?: { __typename?: 'WorkbenchToolSlackConnection', url: string } | null, pagerduty?: { __typename?: 'WorkbenchToolPagerdutyConnection', url: string } | null, teams?: { __typename?: 'WorkbenchToolTeamsConnection', clientId?: string | null, tenantId?: string | null } | null, splunk?: { __typename?: 'WorkbenchToolSplunkConnection', url?: string | null, tokenType?: SplunkTokenType | null, username?: string | null } | null, cloudwatch?: { __typename?: 'WorkbenchToolCloudwatchConnection', logGroupNames?: Array | null, region?: string | null, roleArn?: string | null, roleSessionName?: string | null } | null, azure?: { __typename?: 'WorkbenchToolAzureConnection', subscriptionId?: string | null, tenantId?: string | null, clientId?: string | null, prometheusUrl?: string | null } | null, dynatrace?: { __typename?: 'WorkbenchToolDynatraceConnection', url?: string | null } | null, sentry?: { __typename?: 'WorkbenchToolSentryConnection', url?: string | null } | null, github?: { __typename?: 'WorkbenchToolGithubConnection', url: string, toolset?: string | null, appId?: string | null, installationId?: string | null } | null, gitlab?: { __typename?: 'WorkbenchToolGitlabConnection', url?: string | null } | null, bitbucket?: { __typename?: 'WorkbenchToolBitbucketConnection', url?: string | null } | null, bitbucketDatacenter?: { __typename?: 'WorkbenchToolBitbucketDatacenterConnection', url?: string | null } | null, azureDevops?: { __typename?: 'WorkbenchToolAzureDevopsConnection', url?: string | null } | null, lambda?: { __typename?: 'WorkbenchToolLambdaConnection', lambdaArn?: string | null, description?: string | null, inputSchema?: Record | null } | null, cloudRun?: { __typename?: 'WorkbenchToolCloudRunConnection', identifier?: string | null, description?: string | null, inputSchema?: Record | null } | null, azureFunction?: { __typename?: 'WorkbenchToolAzureFunctionConnection', identifier?: string | null, description?: string | null, inputSchema?: Record | null } | null, docker?: { __typename?: 'WorkbenchToolDockerConnection', url?: string | null, provider?: HelmAuthProvider | null, proxy?: { __typename?: 'HttpProxyConfiguration', url: string, noproxy?: string | null } | null } | null } | null, cloudConnection?: { __typename?: 'CloudConnection', id: string, name: string, provider: Provider } | null, mcpServer?: { __typename?: 'McpServer', id: string, name: string, url: string } | null } | null> | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, botUser?: { __typename?: 'User', id: string, name: string, email: string, profile?: string | null } | null, webhooks?: { __typename?: 'WorkbenchWebhookConnection', edges?: Array<{ __typename?: 'WorkbenchWebhookEdge', node?: { __typename?: 'WorkbenchWebhook', id: string, name?: string | null, priority?: number | null, webhook?: { __typename?: 'ObservabilityWebhook', id: string, type: ObservabilityWebhookType } | null, issueWebhook?: { __typename?: 'IssueWebhook', id: string, provider: IssueWebhookProvider } | null } | null } | null> | null } | null };
+export type WorkbenchFragment = { __typename?: 'Workbench', systemPrompt?: string | null, id: string, name: string, description?: string | null, agentRuntime?: { __typename?: 'AgentRuntime', id: string, name: string, allowedRepositories?: Array | null, type: AgentRuntimeType } | null, repository?: { __typename?: 'GitRepository', id: string } | null, configuration?: { __typename?: 'WorkbenchConfiguration', selfService?: boolean | null, infrastructure?: { __typename?: 'WorkbenchInfrastructure', services?: boolean | null, stacks?: boolean | null, kubernetes?: boolean | null, podLogs?: boolean | null, vulnerabilities?: boolean | null, sentinels?: boolean | null } | null, observability?: { __typename?: 'WorkbenchObservability', logs?: boolean | null, metrics?: boolean | null } | null, coding?: { __typename?: 'WorkbenchCoding', mode?: AgentRunMode | null, repositories?: Array | null, enableBabysitting?: boolean | null } | null } | null, modes?: { __typename?: 'WorkbenchJobModes', plan?: boolean | null, verification?: boolean | null, model?: { __typename?: 'WorkbenchJobModel', provider?: AiProvider | null, model?: string | null } | null, coding?: { __typename?: 'WorkbenchJobCodingModes', approval?: boolean | null, babysit?: boolean | null, review?: boolean | null } | null, budget?: { __typename?: 'WorkbenchJobBudget', cost?: number | null, tokens?: number | null } | null, kubernetes?: { __typename?: 'WorkbenchJobKubernetesModes', update?: boolean | null, delete?: boolean | null, exec?: boolean | null, drain?: boolean | null, excludeNamespaces?: Array | null, requireNamespaces?: Array | null } | null } | null, budget?: { __typename?: 'WorkbenchBudget', enabled?: boolean | null, maximum?: number | null, minFree?: number | null, unit?: WorkbenchBudgetUnit | null, last?: number | null, lastUpdated?: string | null } | null, skills?: { __typename?: 'WorkbenchSkills', files?: Array | null, ref?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, workbenchSkills?: { __typename?: 'WorkbenchSkillConnection', edges?: Array<{ __typename?: 'WorkbenchSkillEdge', node?: { __typename?: 'WorkbenchSkill', id: string, name?: string | null, description?: string | null, contents?: string | null, subagents?: Array | null } | null } | null> | null } | null, workbenchKnowledge?: { __typename?: 'WorkbenchKnowledgeConnection', edges?: Array<{ __typename?: 'WorkbenchKnowledgeEdge', node?: { __typename?: 'WorkbenchKnowledge', id: string, name?: string | null, description?: string | null, knowledge?: string | null, labels?: Array | null, usages?: number | null, lastUsedAt?: string | null } | null } | null> | null } | null, tools?: Array<{ __typename?: 'WorkbenchTool', id: string, name: string, tool: WorkbenchToolType, categories?: Array | null, approval?: boolean | null, scmConnection?: { __typename?: 'ScmConnection', id: string, name: string, type: ScmType } | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, configuration?: { __typename?: 'WorkbenchToolConfiguration', http?: { __typename?: 'WorkbenchToolHttpConfiguration', url?: string | null, method?: string | null, body?: string | null, inputSchema?: Record | null, headers?: Array<{ __typename?: 'WorkbenchToolHttpHeader', name?: string | null, value?: string | null } | null> | null } | null, datadog?: { __typename?: 'WorkbenchToolDatadogConnection', site?: string | null } | null, elastic?: { __typename?: 'WorkbenchToolElasticConnection', index: string, url: string, username: string } | null, opensearch?: { __typename?: 'WorkbenchToolOpensearchConnection', host: string, index: string, awsAccessKeyId?: string | null, awsRegion?: string | null, assumeRoleArn?: string | null, usePodIdentity?: boolean | null } | null, loki?: { __typename?: 'WorkbenchToolLokiConnection', url?: string | null, username?: string | null, tenantId?: string | null } | null, victoriaLogs?: { __typename?: 'WorkbenchToolVictoriaLogsConnection', url?: string | null, username?: string | null, accountId?: string | null, projectId?: string | null } | null, prometheus?: { __typename?: 'WorkbenchToolPrometheusConnection', url?: string | null, username?: string | null, tenantId?: string | null, awsSigv4?: boolean | null, awsAccessKeyId?: string | null, awsRegion?: string | null } | null, tempo?: { __typename?: 'WorkbenchToolTempoConnection', url?: string | null, username?: string | null, tenantId?: string | null } | null, jaeger?: { __typename?: 'WorkbenchToolJaegerConnection', url?: string | null, username?: string | null } | null, atlassian?: { __typename?: 'WorkbenchToolAtlassianConnection', email?: string | null, url: string } | null, jira?: { __typename?: 'WorkbenchToolJiraConnection', email: string, url: string } | null, jiraDatacenter?: { __typename?: 'WorkbenchToolJiraDatacenterConnection', url: string } | null, linear?: { __typename?: 'WorkbenchToolLinearConnection', url: string } | null, slack?: { __typename?: 'WorkbenchToolSlackConnection', url: string } | null, pagerduty?: { __typename?: 'WorkbenchToolPagerdutyConnection', url: string } | null, teams?: { __typename?: 'WorkbenchToolTeamsConnection', clientId?: string | null, tenantId?: string | null } | null, splunk?: { __typename?: 'WorkbenchToolSplunkConnection', url?: string | null, tokenType?: SplunkTokenType | null, username?: string | null } | null, cloudwatch?: { __typename?: 'WorkbenchToolCloudwatchConnection', logGroupNames?: Array | null, region?: string | null, roleArn?: string | null, roleSessionName?: string | null } | null, azure?: { __typename?: 'WorkbenchToolAzureConnection', subscriptionId?: string | null, tenantId?: string | null, clientId?: string | null, prometheusUrl?: string | null } | null, dynatrace?: { __typename?: 'WorkbenchToolDynatraceConnection', url?: string | null } | null, sentry?: { __typename?: 'WorkbenchToolSentryConnection', url?: string | null } | null, github?: { __typename?: 'WorkbenchToolGithubConnection', url: string, toolset?: string | null, appId?: string | null, installationId?: string | null } | null, gitlab?: { __typename?: 'WorkbenchToolGitlabConnection', url?: string | null } | null, bitbucket?: { __typename?: 'WorkbenchToolBitbucketConnection', url?: string | null } | null, bitbucketDatacenter?: { __typename?: 'WorkbenchToolBitbucketDatacenterConnection', url?: string | null } | null, azureDevops?: { __typename?: 'WorkbenchToolAzureDevopsConnection', url?: string | null } | null, lambda?: { __typename?: 'WorkbenchToolLambdaConnection', lambdaArn?: string | null, description?: string | null, inputSchema?: Record | null } | null, cloudRun?: { __typename?: 'WorkbenchToolCloudRunConnection', identifier?: string | null, description?: string | null, inputSchema?: Record | null } | null, azureFunction?: { __typename?: 'WorkbenchToolAzureFunctionConnection', identifier?: string | null, description?: string | null, inputSchema?: Record | null } | null, docker?: { __typename?: 'WorkbenchToolDockerConnection', url?: string | null, provider?: HelmAuthProvider | null, proxy?: { __typename?: 'HttpProxyConfiguration', url: string, noproxy?: string | null } | null } | null } | null, cloudConnection?: { __typename?: 'CloudConnection', id: string, name: string, provider: Provider } | null, mcpServer?: { __typename?: 'McpServer', id: string, name: string, url: string } | null } | null> | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, botUser?: { __typename?: 'User', id: string, name: string, email: string, profile?: string | null } | null, webhooks?: { __typename?: 'WorkbenchWebhookConnection', edges?: Array<{ __typename?: 'WorkbenchWebhookEdge', node?: { __typename?: 'WorkbenchWebhook', id: string, name?: string | null, priority?: number | null, webhook?: { __typename?: 'ObservabilityWebhook', id: string, type: ObservabilityWebhookType } | null, issueWebhook?: { __typename?: 'IssueWebhook', id: string, provider: IssueWebhookProvider } | null } | null } | null> | null } | null };
export type WorkbenchToolTinyFragment = { __typename?: 'WorkbenchTool', id: string, name: string, tool: WorkbenchToolType, categories?: Array | null, approval?: boolean | null, cloudConnection?: { __typename?: 'CloudConnection', id: string, name: string, provider: Provider } | null, mcpServer?: { __typename?: 'McpServer', id: string, name: string, url: string } | null };
@@ -22968,7 +22974,7 @@ export type WorkbenchQueryVariables = Exact<{
}>;
-export type WorkbenchQuery = { __typename?: 'RootQueryType', workbench?: { __typename?: 'Workbench', systemPrompt?: string | null, id: string, name: string, description?: string | null, agentRuntime?: { __typename?: 'AgentRuntime', id: string, name: string, allowedRepositories?: Array | null, type: AgentRuntimeType } | null, repository?: { __typename?: 'GitRepository', id: string } | null, configuration?: { __typename?: 'WorkbenchConfiguration', infrastructure?: { __typename?: 'WorkbenchInfrastructure', services?: boolean | null, stacks?: boolean | null, kubernetes?: boolean | null, podLogs?: boolean | null, vulnerabilities?: boolean | null, sentinels?: boolean | null } | null, observability?: { __typename?: 'WorkbenchObservability', logs?: boolean | null, metrics?: boolean | null } | null, coding?: { __typename?: 'WorkbenchCoding', mode?: AgentRunMode | null, repositories?: Array | null, enableBabysitting?: boolean | null } | null } | null, modes?: { __typename?: 'WorkbenchJobModes', plan?: boolean | null, verification?: boolean | null, model?: { __typename?: 'WorkbenchJobModel', provider?: AiProvider | null, model?: string | null } | null, coding?: { __typename?: 'WorkbenchJobCodingModes', approval?: boolean | null, babysit?: boolean | null, review?: boolean | null } | null, budget?: { __typename?: 'WorkbenchJobBudget', cost?: number | null, tokens?: number | null } | null, kubernetes?: { __typename?: 'WorkbenchJobKubernetesModes', update?: boolean | null, delete?: boolean | null, exec?: boolean | null, drain?: boolean | null, excludeNamespaces?: Array | null, requireNamespaces?: Array | null } | null } | null, budget?: { __typename?: 'WorkbenchBudget', enabled?: boolean | null, maximum?: number | null, minFree?: number | null, unit?: WorkbenchBudgetUnit | null, last?: number | null, lastUpdated?: string | null } | null, skills?: { __typename?: 'WorkbenchSkills', files?: Array | null, ref?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, workbenchSkills?: { __typename?: 'WorkbenchSkillConnection', edges?: Array<{ __typename?: 'WorkbenchSkillEdge', node?: { __typename?: 'WorkbenchSkill', id: string, name?: string | null, description?: string | null, contents?: string | null, subagents?: Array | null } | null } | null> | null } | null, workbenchKnowledge?: { __typename?: 'WorkbenchKnowledgeConnection', edges?: Array<{ __typename?: 'WorkbenchKnowledgeEdge', node?: { __typename?: 'WorkbenchKnowledge', id: string, name?: string | null, description?: string | null, knowledge?: string | null, labels?: Array | null, usages?: number | null, lastUsedAt?: string | null } | null } | null> | null } | null, tools?: Array<{ __typename?: 'WorkbenchTool', id: string, name: string, tool: WorkbenchToolType, categories?: Array | null, approval?: boolean | null, scmConnection?: { __typename?: 'ScmConnection', id: string, name: string, type: ScmType } | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, configuration?: { __typename?: 'WorkbenchToolConfiguration', http?: { __typename?: 'WorkbenchToolHttpConfiguration', url?: string | null, method?: string | null, body?: string | null, inputSchema?: Record | null, headers?: Array<{ __typename?: 'WorkbenchToolHttpHeader', name?: string | null, value?: string | null } | null> | null } | null, datadog?: { __typename?: 'WorkbenchToolDatadogConnection', site?: string | null } | null, elastic?: { __typename?: 'WorkbenchToolElasticConnection', index: string, url: string, username: string } | null, opensearch?: { __typename?: 'WorkbenchToolOpensearchConnection', host: string, index: string, awsAccessKeyId?: string | null, awsRegion?: string | null, assumeRoleArn?: string | null, usePodIdentity?: boolean | null } | null, loki?: { __typename?: 'WorkbenchToolLokiConnection', url?: string | null, username?: string | null, tenantId?: string | null } | null, victoriaLogs?: { __typename?: 'WorkbenchToolVictoriaLogsConnection', url?: string | null, username?: string | null, accountId?: string | null, projectId?: string | null } | null, prometheus?: { __typename?: 'WorkbenchToolPrometheusConnection', url?: string | null, username?: string | null, tenantId?: string | null, awsSigv4?: boolean | null, awsAccessKeyId?: string | null, awsRegion?: string | null } | null, tempo?: { __typename?: 'WorkbenchToolTempoConnection', url?: string | null, username?: string | null, tenantId?: string | null } | null, jaeger?: { __typename?: 'WorkbenchToolJaegerConnection', url?: string | null, username?: string | null } | null, atlassian?: { __typename?: 'WorkbenchToolAtlassianConnection', email?: string | null, url: string } | null, jira?: { __typename?: 'WorkbenchToolJiraConnection', email: string, url: string } | null, jiraDatacenter?: { __typename?: 'WorkbenchToolJiraDatacenterConnection', url: string } | null, linear?: { __typename?: 'WorkbenchToolLinearConnection', url: string } | null, slack?: { __typename?: 'WorkbenchToolSlackConnection', url: string } | null, pagerduty?: { __typename?: 'WorkbenchToolPagerdutyConnection', url: string } | null, teams?: { __typename?: 'WorkbenchToolTeamsConnection', clientId?: string | null, tenantId?: string | null } | null, splunk?: { __typename?: 'WorkbenchToolSplunkConnection', url?: string | null, tokenType?: SplunkTokenType | null, username?: string | null } | null, cloudwatch?: { __typename?: 'WorkbenchToolCloudwatchConnection', logGroupNames?: Array | null, region?: string | null, roleArn?: string | null, roleSessionName?: string | null } | null, azure?: { __typename?: 'WorkbenchToolAzureConnection', subscriptionId?: string | null, tenantId?: string | null, clientId?: string | null, prometheusUrl?: string | null } | null, dynatrace?: { __typename?: 'WorkbenchToolDynatraceConnection', url?: string | null } | null, sentry?: { __typename?: 'WorkbenchToolSentryConnection', url?: string | null } | null, github?: { __typename?: 'WorkbenchToolGithubConnection', url: string, toolset?: string | null, appId?: string | null, installationId?: string | null } | null, gitlab?: { __typename?: 'WorkbenchToolGitlabConnection', url?: string | null } | null, bitbucket?: { __typename?: 'WorkbenchToolBitbucketConnection', url?: string | null } | null, bitbucketDatacenter?: { __typename?: 'WorkbenchToolBitbucketDatacenterConnection', url?: string | null } | null, azureDevops?: { __typename?: 'WorkbenchToolAzureDevopsConnection', url?: string | null } | null, lambda?: { __typename?: 'WorkbenchToolLambdaConnection', lambdaArn?: string | null, description?: string | null, inputSchema?: Record | null } | null, cloudRun?: { __typename?: 'WorkbenchToolCloudRunConnection', identifier?: string | null, description?: string | null, inputSchema?: Record | null } | null, azureFunction?: { __typename?: 'WorkbenchToolAzureFunctionConnection', identifier?: string | null, description?: string | null, inputSchema?: Record | null } | null, docker?: { __typename?: 'WorkbenchToolDockerConnection', url?: string | null, provider?: HelmAuthProvider | null, proxy?: { __typename?: 'HttpProxyConfiguration', url: string, noproxy?: string | null } | null } | null } | null, cloudConnection?: { __typename?: 'CloudConnection', id: string, name: string, provider: Provider } | null, mcpServer?: { __typename?: 'McpServer', id: string, name: string, url: string } | null } | null> | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, botUser?: { __typename?: 'User', id: string, name: string, email: string, profile?: string | null } | null, webhooks?: { __typename?: 'WorkbenchWebhookConnection', edges?: Array<{ __typename?: 'WorkbenchWebhookEdge', node?: { __typename?: 'WorkbenchWebhook', id: string, name?: string | null, priority?: number | null, webhook?: { __typename?: 'ObservabilityWebhook', id: string, type: ObservabilityWebhookType } | null, issueWebhook?: { __typename?: 'IssueWebhook', id: string, provider: IssueWebhookProvider } | null } | null } | null> | null } | null } | null };
+export type WorkbenchQuery = { __typename?: 'RootQueryType', workbench?: { __typename?: 'Workbench', systemPrompt?: string | null, id: string, name: string, description?: string | null, agentRuntime?: { __typename?: 'AgentRuntime', id: string, name: string, allowedRepositories?: Array | null, type: AgentRuntimeType } | null, repository?: { __typename?: 'GitRepository', id: string } | null, configuration?: { __typename?: 'WorkbenchConfiguration', selfService?: boolean | null, infrastructure?: { __typename?: 'WorkbenchInfrastructure', services?: boolean | null, stacks?: boolean | null, kubernetes?: boolean | null, podLogs?: boolean | null, vulnerabilities?: boolean | null, sentinels?: boolean | null } | null, observability?: { __typename?: 'WorkbenchObservability', logs?: boolean | null, metrics?: boolean | null } | null, coding?: { __typename?: 'WorkbenchCoding', mode?: AgentRunMode | null, repositories?: Array | null, enableBabysitting?: boolean | null } | null } | null, modes?: { __typename?: 'WorkbenchJobModes', plan?: boolean | null, verification?: boolean | null, model?: { __typename?: 'WorkbenchJobModel', provider?: AiProvider | null, model?: string | null } | null, coding?: { __typename?: 'WorkbenchJobCodingModes', approval?: boolean | null, babysit?: boolean | null, review?: boolean | null } | null, budget?: { __typename?: 'WorkbenchJobBudget', cost?: number | null, tokens?: number | null } | null, kubernetes?: { __typename?: 'WorkbenchJobKubernetesModes', update?: boolean | null, delete?: boolean | null, exec?: boolean | null, drain?: boolean | null, excludeNamespaces?: Array | null, requireNamespaces?: Array | null } | null } | null, budget?: { __typename?: 'WorkbenchBudget', enabled?: boolean | null, maximum?: number | null, minFree?: number | null, unit?: WorkbenchBudgetUnit | null, last?: number | null, lastUpdated?: string | null } | null, skills?: { __typename?: 'WorkbenchSkills', files?: Array | null, ref?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, workbenchSkills?: { __typename?: 'WorkbenchSkillConnection', edges?: Array<{ __typename?: 'WorkbenchSkillEdge', node?: { __typename?: 'WorkbenchSkill', id: string, name?: string | null, description?: string | null, contents?: string | null, subagents?: Array | null } | null } | null> | null } | null, workbenchKnowledge?: { __typename?: 'WorkbenchKnowledgeConnection', edges?: Array<{ __typename?: 'WorkbenchKnowledgeEdge', node?: { __typename?: 'WorkbenchKnowledge', id: string, name?: string | null, description?: string | null, knowledge?: string | null, labels?: Array | null, usages?: number | null, lastUsedAt?: string | null } | null } | null> | null } | null, tools?: Array<{ __typename?: 'WorkbenchTool', id: string, name: string, tool: WorkbenchToolType, categories?: Array | null, approval?: boolean | null, scmConnection?: { __typename?: 'ScmConnection', id: string, name: string, type: ScmType } | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, configuration?: { __typename?: 'WorkbenchToolConfiguration', http?: { __typename?: 'WorkbenchToolHttpConfiguration', url?: string | null, method?: string | null, body?: string | null, inputSchema?: Record | null, headers?: Array<{ __typename?: 'WorkbenchToolHttpHeader', name?: string | null, value?: string | null } | null> | null } | null, datadog?: { __typename?: 'WorkbenchToolDatadogConnection', site?: string | null } | null, elastic?: { __typename?: 'WorkbenchToolElasticConnection', index: string, url: string, username: string } | null, opensearch?: { __typename?: 'WorkbenchToolOpensearchConnection', host: string, index: string, awsAccessKeyId?: string | null, awsRegion?: string | null, assumeRoleArn?: string | null, usePodIdentity?: boolean | null } | null, loki?: { __typename?: 'WorkbenchToolLokiConnection', url?: string | null, username?: string | null, tenantId?: string | null } | null, victoriaLogs?: { __typename?: 'WorkbenchToolVictoriaLogsConnection', url?: string | null, username?: string | null, accountId?: string | null, projectId?: string | null } | null, prometheus?: { __typename?: 'WorkbenchToolPrometheusConnection', url?: string | null, username?: string | null, tenantId?: string | null, awsSigv4?: boolean | null, awsAccessKeyId?: string | null, awsRegion?: string | null } | null, tempo?: { __typename?: 'WorkbenchToolTempoConnection', url?: string | null, username?: string | null, tenantId?: string | null } | null, jaeger?: { __typename?: 'WorkbenchToolJaegerConnection', url?: string | null, username?: string | null } | null, atlassian?: { __typename?: 'WorkbenchToolAtlassianConnection', email?: string | null, url: string } | null, jira?: { __typename?: 'WorkbenchToolJiraConnection', email: string, url: string } | null, jiraDatacenter?: { __typename?: 'WorkbenchToolJiraDatacenterConnection', url: string } | null, linear?: { __typename?: 'WorkbenchToolLinearConnection', url: string } | null, slack?: { __typename?: 'WorkbenchToolSlackConnection', url: string } | null, pagerduty?: { __typename?: 'WorkbenchToolPagerdutyConnection', url: string } | null, teams?: { __typename?: 'WorkbenchToolTeamsConnection', clientId?: string | null, tenantId?: string | null } | null, splunk?: { __typename?: 'WorkbenchToolSplunkConnection', url?: string | null, tokenType?: SplunkTokenType | null, username?: string | null } | null, cloudwatch?: { __typename?: 'WorkbenchToolCloudwatchConnection', logGroupNames?: Array | null, region?: string | null, roleArn?: string | null, roleSessionName?: string | null } | null, azure?: { __typename?: 'WorkbenchToolAzureConnection', subscriptionId?: string | null, tenantId?: string | null, clientId?: string | null, prometheusUrl?: string | null } | null, dynatrace?: { __typename?: 'WorkbenchToolDynatraceConnection', url?: string | null } | null, sentry?: { __typename?: 'WorkbenchToolSentryConnection', url?: string | null } | null, github?: { __typename?: 'WorkbenchToolGithubConnection', url: string, toolset?: string | null, appId?: string | null, installationId?: string | null } | null, gitlab?: { __typename?: 'WorkbenchToolGitlabConnection', url?: string | null } | null, bitbucket?: { __typename?: 'WorkbenchToolBitbucketConnection', url?: string | null } | null, bitbucketDatacenter?: { __typename?: 'WorkbenchToolBitbucketDatacenterConnection', url?: string | null } | null, azureDevops?: { __typename?: 'WorkbenchToolAzureDevopsConnection', url?: string | null } | null, lambda?: { __typename?: 'WorkbenchToolLambdaConnection', lambdaArn?: string | null, description?: string | null, inputSchema?: Record | null } | null, cloudRun?: { __typename?: 'WorkbenchToolCloudRunConnection', identifier?: string | null, description?: string | null, inputSchema?: Record | null } | null, azureFunction?: { __typename?: 'WorkbenchToolAzureFunctionConnection', identifier?: string | null, description?: string | null, inputSchema?: Record | null } | null, docker?: { __typename?: 'WorkbenchToolDockerConnection', url?: string | null, provider?: HelmAuthProvider | null, proxy?: { __typename?: 'HttpProxyConfiguration', url: string, noproxy?: string | null } | null } | null } | null, cloudConnection?: { __typename?: 'CloudConnection', id: string, name: string, provider: Provider } | null, mcpServer?: { __typename?: 'McpServer', id: string, name: string, url: string } | null } | null> | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, botUser?: { __typename?: 'User', id: string, name: string, email: string, profile?: string | null } | null, webhooks?: { __typename?: 'WorkbenchWebhookConnection', edges?: Array<{ __typename?: 'WorkbenchWebhookEdge', node?: { __typename?: 'WorkbenchWebhook', id: string, name?: string | null, priority?: number | null, webhook?: { __typename?: 'ObservabilityWebhook', id: string, type: ObservabilityWebhookType } | null, issueWebhook?: { __typename?: 'IssueWebhook', id: string, provider: IssueWebhookProvider } | null } | null } | null> | null } | null } | null };
export type WorkbenchAccessibleUserFragment = { __typename?: 'User', id: string, name: string, email: string, profile?: string | null };
@@ -23289,7 +23295,7 @@ export type CreateWorkbenchMutationVariables = Exact<{
}>;
-export type CreateWorkbenchMutation = { __typename?: 'RootMutationType', createWorkbench?: { __typename?: 'Workbench', systemPrompt?: string | null, id: string, name: string, description?: string | null, agentRuntime?: { __typename?: 'AgentRuntime', id: string, name: string, allowedRepositories?: Array | null, type: AgentRuntimeType } | null, repository?: { __typename?: 'GitRepository', id: string } | null, configuration?: { __typename?: 'WorkbenchConfiguration', infrastructure?: { __typename?: 'WorkbenchInfrastructure', services?: boolean | null, stacks?: boolean | null, kubernetes?: boolean | null, podLogs?: boolean | null, vulnerabilities?: boolean | null, sentinels?: boolean | null } | null, observability?: { __typename?: 'WorkbenchObservability', logs?: boolean | null, metrics?: boolean | null } | null, coding?: { __typename?: 'WorkbenchCoding', mode?: AgentRunMode | null, repositories?: Array | null, enableBabysitting?: boolean | null } | null } | null, modes?: { __typename?: 'WorkbenchJobModes', plan?: boolean | null, verification?: boolean | null, model?: { __typename?: 'WorkbenchJobModel', provider?: AiProvider | null, model?: string | null } | null, coding?: { __typename?: 'WorkbenchJobCodingModes', approval?: boolean | null, babysit?: boolean | null, review?: boolean | null } | null, budget?: { __typename?: 'WorkbenchJobBudget', cost?: number | null, tokens?: number | null } | null, kubernetes?: { __typename?: 'WorkbenchJobKubernetesModes', update?: boolean | null, delete?: boolean | null, exec?: boolean | null, drain?: boolean | null, excludeNamespaces?: Array | null, requireNamespaces?: Array | null } | null } | null, budget?: { __typename?: 'WorkbenchBudget', enabled?: boolean | null, maximum?: number | null, minFree?: number | null, unit?: WorkbenchBudgetUnit | null, last?: number | null, lastUpdated?: string | null } | null, skills?: { __typename?: 'WorkbenchSkills', files?: Array | null, ref?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, workbenchSkills?: { __typename?: 'WorkbenchSkillConnection', edges?: Array<{ __typename?: 'WorkbenchSkillEdge', node?: { __typename?: 'WorkbenchSkill', id: string, name?: string | null, description?: string | null, contents?: string | null, subagents?: Array | null } | null } | null> | null } | null, workbenchKnowledge?: { __typename?: 'WorkbenchKnowledgeConnection', edges?: Array<{ __typename?: 'WorkbenchKnowledgeEdge', node?: { __typename?: 'WorkbenchKnowledge', id: string, name?: string | null, description?: string | null, knowledge?: string | null, labels?: Array | null, usages?: number | null, lastUsedAt?: string | null } | null } | null> | null } | null, tools?: Array<{ __typename?: 'WorkbenchTool', id: string, name: string, tool: WorkbenchToolType, categories?: Array | null, approval?: boolean | null, scmConnection?: { __typename?: 'ScmConnection', id: string, name: string, type: ScmType } | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, configuration?: { __typename?: 'WorkbenchToolConfiguration', http?: { __typename?: 'WorkbenchToolHttpConfiguration', url?: string | null, method?: string | null, body?: string | null, inputSchema?: Record | null, headers?: Array<{ __typename?: 'WorkbenchToolHttpHeader', name?: string | null, value?: string | null } | null> | null } | null, datadog?: { __typename?: 'WorkbenchToolDatadogConnection', site?: string | null } | null, elastic?: { __typename?: 'WorkbenchToolElasticConnection', index: string, url: string, username: string } | null, opensearch?: { __typename?: 'WorkbenchToolOpensearchConnection', host: string, index: string, awsAccessKeyId?: string | null, awsRegion?: string | null, assumeRoleArn?: string | null, usePodIdentity?: boolean | null } | null, loki?: { __typename?: 'WorkbenchToolLokiConnection', url?: string | null, username?: string | null, tenantId?: string | null } | null, victoriaLogs?: { __typename?: 'WorkbenchToolVictoriaLogsConnection', url?: string | null, username?: string | null, accountId?: string | null, projectId?: string | null } | null, prometheus?: { __typename?: 'WorkbenchToolPrometheusConnection', url?: string | null, username?: string | null, tenantId?: string | null, awsSigv4?: boolean | null, awsAccessKeyId?: string | null, awsRegion?: string | null } | null, tempo?: { __typename?: 'WorkbenchToolTempoConnection', url?: string | null, username?: string | null, tenantId?: string | null } | null, jaeger?: { __typename?: 'WorkbenchToolJaegerConnection', url?: string | null, username?: string | null } | null, atlassian?: { __typename?: 'WorkbenchToolAtlassianConnection', email?: string | null, url: string } | null, jira?: { __typename?: 'WorkbenchToolJiraConnection', email: string, url: string } | null, jiraDatacenter?: { __typename?: 'WorkbenchToolJiraDatacenterConnection', url: string } | null, linear?: { __typename?: 'WorkbenchToolLinearConnection', url: string } | null, slack?: { __typename?: 'WorkbenchToolSlackConnection', url: string } | null, pagerduty?: { __typename?: 'WorkbenchToolPagerdutyConnection', url: string } | null, teams?: { __typename?: 'WorkbenchToolTeamsConnection', clientId?: string | null, tenantId?: string | null } | null, splunk?: { __typename?: 'WorkbenchToolSplunkConnection', url?: string | null, tokenType?: SplunkTokenType | null, username?: string | null } | null, cloudwatch?: { __typename?: 'WorkbenchToolCloudwatchConnection', logGroupNames?: Array | null, region?: string | null, roleArn?: string | null, roleSessionName?: string | null } | null, azure?: { __typename?: 'WorkbenchToolAzureConnection', subscriptionId?: string | null, tenantId?: string | null, clientId?: string | null, prometheusUrl?: string | null } | null, dynatrace?: { __typename?: 'WorkbenchToolDynatraceConnection', url?: string | null } | null, sentry?: { __typename?: 'WorkbenchToolSentryConnection', url?: string | null } | null, github?: { __typename?: 'WorkbenchToolGithubConnection', url: string, toolset?: string | null, appId?: string | null, installationId?: string | null } | null, gitlab?: { __typename?: 'WorkbenchToolGitlabConnection', url?: string | null } | null, bitbucket?: { __typename?: 'WorkbenchToolBitbucketConnection', url?: string | null } | null, bitbucketDatacenter?: { __typename?: 'WorkbenchToolBitbucketDatacenterConnection', url?: string | null } | null, azureDevops?: { __typename?: 'WorkbenchToolAzureDevopsConnection', url?: string | null } | null, lambda?: { __typename?: 'WorkbenchToolLambdaConnection', lambdaArn?: string | null, description?: string | null, inputSchema?: Record | null } | null, cloudRun?: { __typename?: 'WorkbenchToolCloudRunConnection', identifier?: string | null, description?: string | null, inputSchema?: Record | null } | null, azureFunction?: { __typename?: 'WorkbenchToolAzureFunctionConnection', identifier?: string | null, description?: string | null, inputSchema?: Record | null } | null, docker?: { __typename?: 'WorkbenchToolDockerConnection', url?: string | null, provider?: HelmAuthProvider | null, proxy?: { __typename?: 'HttpProxyConfiguration', url: string, noproxy?: string | null } | null } | null } | null, cloudConnection?: { __typename?: 'CloudConnection', id: string, name: string, provider: Provider } | null, mcpServer?: { __typename?: 'McpServer', id: string, name: string, url: string } | null } | null> | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, botUser?: { __typename?: 'User', id: string, name: string, email: string, profile?: string | null } | null, webhooks?: { __typename?: 'WorkbenchWebhookConnection', edges?: Array<{ __typename?: 'WorkbenchWebhookEdge', node?: { __typename?: 'WorkbenchWebhook', id: string, name?: string | null, priority?: number | null, webhook?: { __typename?: 'ObservabilityWebhook', id: string, type: ObservabilityWebhookType } | null, issueWebhook?: { __typename?: 'IssueWebhook', id: string, provider: IssueWebhookProvider } | null } | null } | null> | null } | null } | null };
+export type CreateWorkbenchMutation = { __typename?: 'RootMutationType', createWorkbench?: { __typename?: 'Workbench', systemPrompt?: string | null, id: string, name: string, description?: string | null, agentRuntime?: { __typename?: 'AgentRuntime', id: string, name: string, allowedRepositories?: Array | null, type: AgentRuntimeType } | null, repository?: { __typename?: 'GitRepository', id: string } | null, configuration?: { __typename?: 'WorkbenchConfiguration', selfService?: boolean | null, infrastructure?: { __typename?: 'WorkbenchInfrastructure', services?: boolean | null, stacks?: boolean | null, kubernetes?: boolean | null, podLogs?: boolean | null, vulnerabilities?: boolean | null, sentinels?: boolean | null } | null, observability?: { __typename?: 'WorkbenchObservability', logs?: boolean | null, metrics?: boolean | null } | null, coding?: { __typename?: 'WorkbenchCoding', mode?: AgentRunMode | null, repositories?: Array | null, enableBabysitting?: boolean | null } | null } | null, modes?: { __typename?: 'WorkbenchJobModes', plan?: boolean | null, verification?: boolean | null, model?: { __typename?: 'WorkbenchJobModel', provider?: AiProvider | null, model?: string | null } | null, coding?: { __typename?: 'WorkbenchJobCodingModes', approval?: boolean | null, babysit?: boolean | null, review?: boolean | null } | null, budget?: { __typename?: 'WorkbenchJobBudget', cost?: number | null, tokens?: number | null } | null, kubernetes?: { __typename?: 'WorkbenchJobKubernetesModes', update?: boolean | null, delete?: boolean | null, exec?: boolean | null, drain?: boolean | null, excludeNamespaces?: Array | null, requireNamespaces?: Array | null } | null } | null, budget?: { __typename?: 'WorkbenchBudget', enabled?: boolean | null, maximum?: number | null, minFree?: number | null, unit?: WorkbenchBudgetUnit | null, last?: number | null, lastUpdated?: string | null } | null, skills?: { __typename?: 'WorkbenchSkills', files?: Array | null, ref?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, workbenchSkills?: { __typename?: 'WorkbenchSkillConnection', edges?: Array<{ __typename?: 'WorkbenchSkillEdge', node?: { __typename?: 'WorkbenchSkill', id: string, name?: string | null, description?: string | null, contents?: string | null, subagents?: Array | null } | null } | null> | null } | null, workbenchKnowledge?: { __typename?: 'WorkbenchKnowledgeConnection', edges?: Array<{ __typename?: 'WorkbenchKnowledgeEdge', node?: { __typename?: 'WorkbenchKnowledge', id: string, name?: string | null, description?: string | null, knowledge?: string | null, labels?: Array | null, usages?: number | null, lastUsedAt?: string | null } | null } | null> | null } | null, tools?: Array<{ __typename?: 'WorkbenchTool', id: string, name: string, tool: WorkbenchToolType, categories?: Array | null, approval?: boolean | null, scmConnection?: { __typename?: 'ScmConnection', id: string, name: string, type: ScmType } | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, configuration?: { __typename?: 'WorkbenchToolConfiguration', http?: { __typename?: 'WorkbenchToolHttpConfiguration', url?: string | null, method?: string | null, body?: string | null, inputSchema?: Record | null, headers?: Array<{ __typename?: 'WorkbenchToolHttpHeader', name?: string | null, value?: string | null } | null> | null } | null, datadog?: { __typename?: 'WorkbenchToolDatadogConnection', site?: string | null } | null, elastic?: { __typename?: 'WorkbenchToolElasticConnection', index: string, url: string, username: string } | null, opensearch?: { __typename?: 'WorkbenchToolOpensearchConnection', host: string, index: string, awsAccessKeyId?: string | null, awsRegion?: string | null, assumeRoleArn?: string | null, usePodIdentity?: boolean | null } | null, loki?: { __typename?: 'WorkbenchToolLokiConnection', url?: string | null, username?: string | null, tenantId?: string | null } | null, victoriaLogs?: { __typename?: 'WorkbenchToolVictoriaLogsConnection', url?: string | null, username?: string | null, accountId?: string | null, projectId?: string | null } | null, prometheus?: { __typename?: 'WorkbenchToolPrometheusConnection', url?: string | null, username?: string | null, tenantId?: string | null, awsSigv4?: boolean | null, awsAccessKeyId?: string | null, awsRegion?: string | null } | null, tempo?: { __typename?: 'WorkbenchToolTempoConnection', url?: string | null, username?: string | null, tenantId?: string | null } | null, jaeger?: { __typename?: 'WorkbenchToolJaegerConnection', url?: string | null, username?: string | null } | null, atlassian?: { __typename?: 'WorkbenchToolAtlassianConnection', email?: string | null, url: string } | null, jira?: { __typename?: 'WorkbenchToolJiraConnection', email: string, url: string } | null, jiraDatacenter?: { __typename?: 'WorkbenchToolJiraDatacenterConnection', url: string } | null, linear?: { __typename?: 'WorkbenchToolLinearConnection', url: string } | null, slack?: { __typename?: 'WorkbenchToolSlackConnection', url: string } | null, pagerduty?: { __typename?: 'WorkbenchToolPagerdutyConnection', url: string } | null, teams?: { __typename?: 'WorkbenchToolTeamsConnection', clientId?: string | null, tenantId?: string | null } | null, splunk?: { __typename?: 'WorkbenchToolSplunkConnection', url?: string | null, tokenType?: SplunkTokenType | null, username?: string | null } | null, cloudwatch?: { __typename?: 'WorkbenchToolCloudwatchConnection', logGroupNames?: Array | null, region?: string | null, roleArn?: string | null, roleSessionName?: string | null } | null, azure?: { __typename?: 'WorkbenchToolAzureConnection', subscriptionId?: string | null, tenantId?: string | null, clientId?: string | null, prometheusUrl?: string | null } | null, dynatrace?: { __typename?: 'WorkbenchToolDynatraceConnection', url?: string | null } | null, sentry?: { __typename?: 'WorkbenchToolSentryConnection', url?: string | null } | null, github?: { __typename?: 'WorkbenchToolGithubConnection', url: string, toolset?: string | null, appId?: string | null, installationId?: string | null } | null, gitlab?: { __typename?: 'WorkbenchToolGitlabConnection', url?: string | null } | null, bitbucket?: { __typename?: 'WorkbenchToolBitbucketConnection', url?: string | null } | null, bitbucketDatacenter?: { __typename?: 'WorkbenchToolBitbucketDatacenterConnection', url?: string | null } | null, azureDevops?: { __typename?: 'WorkbenchToolAzureDevopsConnection', url?: string | null } | null, lambda?: { __typename?: 'WorkbenchToolLambdaConnection', lambdaArn?: string | null, description?: string | null, inputSchema?: Record | null } | null, cloudRun?: { __typename?: 'WorkbenchToolCloudRunConnection', identifier?: string | null, description?: string | null, inputSchema?: Record | null } | null, azureFunction?: { __typename?: 'WorkbenchToolAzureFunctionConnection', identifier?: string | null, description?: string | null, inputSchema?: Record | null } | null, docker?: { __typename?: 'WorkbenchToolDockerConnection', url?: string | null, provider?: HelmAuthProvider | null, proxy?: { __typename?: 'HttpProxyConfiguration', url: string, noproxy?: string | null } | null } | null } | null, cloudConnection?: { __typename?: 'CloudConnection', id: string, name: string, provider: Provider } | null, mcpServer?: { __typename?: 'McpServer', id: string, name: string, url: string } | null } | null> | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, botUser?: { __typename?: 'User', id: string, name: string, email: string, profile?: string | null } | null, webhooks?: { __typename?: 'WorkbenchWebhookConnection', edges?: Array<{ __typename?: 'WorkbenchWebhookEdge', node?: { __typename?: 'WorkbenchWebhook', id: string, name?: string | null, priority?: number | null, webhook?: { __typename?: 'ObservabilityWebhook', id: string, type: ObservabilityWebhookType } | null, issueWebhook?: { __typename?: 'IssueWebhook', id: string, provider: IssueWebhookProvider } | null } | null } | null> | null } | null } | null };
export type UpdateWorkbenchMutationVariables = Exact<{
id: Scalars['ID']['input'];
@@ -23297,7 +23303,7 @@ export type UpdateWorkbenchMutationVariables = Exact<{
}>;
-export type UpdateWorkbenchMutation = { __typename?: 'RootMutationType', updateWorkbench?: { __typename?: 'Workbench', systemPrompt?: string | null, id: string, name: string, description?: string | null, agentRuntime?: { __typename?: 'AgentRuntime', id: string, name: string, allowedRepositories?: Array | null, type: AgentRuntimeType } | null, repository?: { __typename?: 'GitRepository', id: string } | null, configuration?: { __typename?: 'WorkbenchConfiguration', infrastructure?: { __typename?: 'WorkbenchInfrastructure', services?: boolean | null, stacks?: boolean | null, kubernetes?: boolean | null, podLogs?: boolean | null, vulnerabilities?: boolean | null, sentinels?: boolean | null } | null, observability?: { __typename?: 'WorkbenchObservability', logs?: boolean | null, metrics?: boolean | null } | null, coding?: { __typename?: 'WorkbenchCoding', mode?: AgentRunMode | null, repositories?: Array | null, enableBabysitting?: boolean | null } | null } | null, modes?: { __typename?: 'WorkbenchJobModes', plan?: boolean | null, verification?: boolean | null, model?: { __typename?: 'WorkbenchJobModel', provider?: AiProvider | null, model?: string | null } | null, coding?: { __typename?: 'WorkbenchJobCodingModes', approval?: boolean | null, babysit?: boolean | null, review?: boolean | null } | null, budget?: { __typename?: 'WorkbenchJobBudget', cost?: number | null, tokens?: number | null } | null, kubernetes?: { __typename?: 'WorkbenchJobKubernetesModes', update?: boolean | null, delete?: boolean | null, exec?: boolean | null, drain?: boolean | null, excludeNamespaces?: Array | null, requireNamespaces?: Array | null } | null } | null, budget?: { __typename?: 'WorkbenchBudget', enabled?: boolean | null, maximum?: number | null, minFree?: number | null, unit?: WorkbenchBudgetUnit | null, last?: number | null, lastUpdated?: string | null } | null, skills?: { __typename?: 'WorkbenchSkills', files?: Array | null, ref?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, workbenchSkills?: { __typename?: 'WorkbenchSkillConnection', edges?: Array<{ __typename?: 'WorkbenchSkillEdge', node?: { __typename?: 'WorkbenchSkill', id: string, name?: string | null, description?: string | null, contents?: string | null, subagents?: Array | null } | null } | null> | null } | null, workbenchKnowledge?: { __typename?: 'WorkbenchKnowledgeConnection', edges?: Array<{ __typename?: 'WorkbenchKnowledgeEdge', node?: { __typename?: 'WorkbenchKnowledge', id: string, name?: string | null, description?: string | null, knowledge?: string | null, labels?: Array | null, usages?: number | null, lastUsedAt?: string | null } | null } | null> | null } | null, tools?: Array<{ __typename?: 'WorkbenchTool', id: string, name: string, tool: WorkbenchToolType, categories?: Array | null, approval?: boolean | null, scmConnection?: { __typename?: 'ScmConnection', id: string, name: string, type: ScmType } | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, configuration?: { __typename?: 'WorkbenchToolConfiguration', http?: { __typename?: 'WorkbenchToolHttpConfiguration', url?: string | null, method?: string | null, body?: string | null, inputSchema?: Record | null, headers?: Array<{ __typename?: 'WorkbenchToolHttpHeader', name?: string | null, value?: string | null } | null> | null } | null, datadog?: { __typename?: 'WorkbenchToolDatadogConnection', site?: string | null } | null, elastic?: { __typename?: 'WorkbenchToolElasticConnection', index: string, url: string, username: string } | null, opensearch?: { __typename?: 'WorkbenchToolOpensearchConnection', host: string, index: string, awsAccessKeyId?: string | null, awsRegion?: string | null, assumeRoleArn?: string | null, usePodIdentity?: boolean | null } | null, loki?: { __typename?: 'WorkbenchToolLokiConnection', url?: string | null, username?: string | null, tenantId?: string | null } | null, victoriaLogs?: { __typename?: 'WorkbenchToolVictoriaLogsConnection', url?: string | null, username?: string | null, accountId?: string | null, projectId?: string | null } | null, prometheus?: { __typename?: 'WorkbenchToolPrometheusConnection', url?: string | null, username?: string | null, tenantId?: string | null, awsSigv4?: boolean | null, awsAccessKeyId?: string | null, awsRegion?: string | null } | null, tempo?: { __typename?: 'WorkbenchToolTempoConnection', url?: string | null, username?: string | null, tenantId?: string | null } | null, jaeger?: { __typename?: 'WorkbenchToolJaegerConnection', url?: string | null, username?: string | null } | null, atlassian?: { __typename?: 'WorkbenchToolAtlassianConnection', email?: string | null, url: string } | null, jira?: { __typename?: 'WorkbenchToolJiraConnection', email: string, url: string } | null, jiraDatacenter?: { __typename?: 'WorkbenchToolJiraDatacenterConnection', url: string } | null, linear?: { __typename?: 'WorkbenchToolLinearConnection', url: string } | null, slack?: { __typename?: 'WorkbenchToolSlackConnection', url: string } | null, pagerduty?: { __typename?: 'WorkbenchToolPagerdutyConnection', url: string } | null, teams?: { __typename?: 'WorkbenchToolTeamsConnection', clientId?: string | null, tenantId?: string | null } | null, splunk?: { __typename?: 'WorkbenchToolSplunkConnection', url?: string | null, tokenType?: SplunkTokenType | null, username?: string | null } | null, cloudwatch?: { __typename?: 'WorkbenchToolCloudwatchConnection', logGroupNames?: Array | null, region?: string | null, roleArn?: string | null, roleSessionName?: string | null } | null, azure?: { __typename?: 'WorkbenchToolAzureConnection', subscriptionId?: string | null, tenantId?: string | null, clientId?: string | null, prometheusUrl?: string | null } | null, dynatrace?: { __typename?: 'WorkbenchToolDynatraceConnection', url?: string | null } | null, sentry?: { __typename?: 'WorkbenchToolSentryConnection', url?: string | null } | null, github?: { __typename?: 'WorkbenchToolGithubConnection', url: string, toolset?: string | null, appId?: string | null, installationId?: string | null } | null, gitlab?: { __typename?: 'WorkbenchToolGitlabConnection', url?: string | null } | null, bitbucket?: { __typename?: 'WorkbenchToolBitbucketConnection', url?: string | null } | null, bitbucketDatacenter?: { __typename?: 'WorkbenchToolBitbucketDatacenterConnection', url?: string | null } | null, azureDevops?: { __typename?: 'WorkbenchToolAzureDevopsConnection', url?: string | null } | null, lambda?: { __typename?: 'WorkbenchToolLambdaConnection', lambdaArn?: string | null, description?: string | null, inputSchema?: Record | null } | null, cloudRun?: { __typename?: 'WorkbenchToolCloudRunConnection', identifier?: string | null, description?: string | null, inputSchema?: Record | null } | null, azureFunction?: { __typename?: 'WorkbenchToolAzureFunctionConnection', identifier?: string | null, description?: string | null, inputSchema?: Record | null } | null, docker?: { __typename?: 'WorkbenchToolDockerConnection', url?: string | null, provider?: HelmAuthProvider | null, proxy?: { __typename?: 'HttpProxyConfiguration', url: string, noproxy?: string | null } | null } | null } | null, cloudConnection?: { __typename?: 'CloudConnection', id: string, name: string, provider: Provider } | null, mcpServer?: { __typename?: 'McpServer', id: string, name: string, url: string } | null } | null> | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, botUser?: { __typename?: 'User', id: string, name: string, email: string, profile?: string | null } | null, webhooks?: { __typename?: 'WorkbenchWebhookConnection', edges?: Array<{ __typename?: 'WorkbenchWebhookEdge', node?: { __typename?: 'WorkbenchWebhook', id: string, name?: string | null, priority?: number | null, webhook?: { __typename?: 'ObservabilityWebhook', id: string, type: ObservabilityWebhookType } | null, issueWebhook?: { __typename?: 'IssueWebhook', id: string, provider: IssueWebhookProvider } | null } | null } | null> | null } | null } | null };
+export type UpdateWorkbenchMutation = { __typename?: 'RootMutationType', updateWorkbench?: { __typename?: 'Workbench', systemPrompt?: string | null, id: string, name: string, description?: string | null, agentRuntime?: { __typename?: 'AgentRuntime', id: string, name: string, allowedRepositories?: Array | null, type: AgentRuntimeType } | null, repository?: { __typename?: 'GitRepository', id: string } | null, configuration?: { __typename?: 'WorkbenchConfiguration', selfService?: boolean | null, infrastructure?: { __typename?: 'WorkbenchInfrastructure', services?: boolean | null, stacks?: boolean | null, kubernetes?: boolean | null, podLogs?: boolean | null, vulnerabilities?: boolean | null, sentinels?: boolean | null } | null, observability?: { __typename?: 'WorkbenchObservability', logs?: boolean | null, metrics?: boolean | null } | null, coding?: { __typename?: 'WorkbenchCoding', mode?: AgentRunMode | null, repositories?: Array | null, enableBabysitting?: boolean | null } | null } | null, modes?: { __typename?: 'WorkbenchJobModes', plan?: boolean | null, verification?: boolean | null, model?: { __typename?: 'WorkbenchJobModel', provider?: AiProvider | null, model?: string | null } | null, coding?: { __typename?: 'WorkbenchJobCodingModes', approval?: boolean | null, babysit?: boolean | null, review?: boolean | null } | null, budget?: { __typename?: 'WorkbenchJobBudget', cost?: number | null, tokens?: number | null } | null, kubernetes?: { __typename?: 'WorkbenchJobKubernetesModes', update?: boolean | null, delete?: boolean | null, exec?: boolean | null, drain?: boolean | null, excludeNamespaces?: Array | null, requireNamespaces?: Array | null } | null } | null, budget?: { __typename?: 'WorkbenchBudget', enabled?: boolean | null, maximum?: number | null, minFree?: number | null, unit?: WorkbenchBudgetUnit | null, last?: number | null, lastUpdated?: string | null } | null, skills?: { __typename?: 'WorkbenchSkills', files?: Array | null, ref?: { __typename?: 'GitRef', ref: string, folder: string } | null } | null, workbenchSkills?: { __typename?: 'WorkbenchSkillConnection', edges?: Array<{ __typename?: 'WorkbenchSkillEdge', node?: { __typename?: 'WorkbenchSkill', id: string, name?: string | null, description?: string | null, contents?: string | null, subagents?: Array | null } | null } | null> | null } | null, workbenchKnowledge?: { __typename?: 'WorkbenchKnowledgeConnection', edges?: Array<{ __typename?: 'WorkbenchKnowledgeEdge', node?: { __typename?: 'WorkbenchKnowledge', id: string, name?: string | null, description?: string | null, knowledge?: string | null, labels?: Array | null, usages?: number | null, lastUsedAt?: string | null } | null } | null> | null } | null, tools?: Array<{ __typename?: 'WorkbenchTool', id: string, name: string, tool: WorkbenchToolType, categories?: Array | null, approval?: boolean | null, scmConnection?: { __typename?: 'ScmConnection', id: string, name: string, type: ScmType } | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, configuration?: { __typename?: 'WorkbenchToolConfiguration', http?: { __typename?: 'WorkbenchToolHttpConfiguration', url?: string | null, method?: string | null, body?: string | null, inputSchema?: Record | null, headers?: Array<{ __typename?: 'WorkbenchToolHttpHeader', name?: string | null, value?: string | null } | null> | null } | null, datadog?: { __typename?: 'WorkbenchToolDatadogConnection', site?: string | null } | null, elastic?: { __typename?: 'WorkbenchToolElasticConnection', index: string, url: string, username: string } | null, opensearch?: { __typename?: 'WorkbenchToolOpensearchConnection', host: string, index: string, awsAccessKeyId?: string | null, awsRegion?: string | null, assumeRoleArn?: string | null, usePodIdentity?: boolean | null } | null, loki?: { __typename?: 'WorkbenchToolLokiConnection', url?: string | null, username?: string | null, tenantId?: string | null } | null, victoriaLogs?: { __typename?: 'WorkbenchToolVictoriaLogsConnection', url?: string | null, username?: string | null, accountId?: string | null, projectId?: string | null } | null, prometheus?: { __typename?: 'WorkbenchToolPrometheusConnection', url?: string | null, username?: string | null, tenantId?: string | null, awsSigv4?: boolean | null, awsAccessKeyId?: string | null, awsRegion?: string | null } | null, tempo?: { __typename?: 'WorkbenchToolTempoConnection', url?: string | null, username?: string | null, tenantId?: string | null } | null, jaeger?: { __typename?: 'WorkbenchToolJaegerConnection', url?: string | null, username?: string | null } | null, atlassian?: { __typename?: 'WorkbenchToolAtlassianConnection', email?: string | null, url: string } | null, jira?: { __typename?: 'WorkbenchToolJiraConnection', email: string, url: string } | null, jiraDatacenter?: { __typename?: 'WorkbenchToolJiraDatacenterConnection', url: string } | null, linear?: { __typename?: 'WorkbenchToolLinearConnection', url: string } | null, slack?: { __typename?: 'WorkbenchToolSlackConnection', url: string } | null, pagerduty?: { __typename?: 'WorkbenchToolPagerdutyConnection', url: string } | null, teams?: { __typename?: 'WorkbenchToolTeamsConnection', clientId?: string | null, tenantId?: string | null } | null, splunk?: { __typename?: 'WorkbenchToolSplunkConnection', url?: string | null, tokenType?: SplunkTokenType | null, username?: string | null } | null, cloudwatch?: { __typename?: 'WorkbenchToolCloudwatchConnection', logGroupNames?: Array | null, region?: string | null, roleArn?: string | null, roleSessionName?: string | null } | null, azure?: { __typename?: 'WorkbenchToolAzureConnection', subscriptionId?: string | null, tenantId?: string | null, clientId?: string | null, prometheusUrl?: string | null } | null, dynatrace?: { __typename?: 'WorkbenchToolDynatraceConnection', url?: string | null } | null, sentry?: { __typename?: 'WorkbenchToolSentryConnection', url?: string | null } | null, github?: { __typename?: 'WorkbenchToolGithubConnection', url: string, toolset?: string | null, appId?: string | null, installationId?: string | null } | null, gitlab?: { __typename?: 'WorkbenchToolGitlabConnection', url?: string | null } | null, bitbucket?: { __typename?: 'WorkbenchToolBitbucketConnection', url?: string | null } | null, bitbucketDatacenter?: { __typename?: 'WorkbenchToolBitbucketDatacenterConnection', url?: string | null } | null, azureDevops?: { __typename?: 'WorkbenchToolAzureDevopsConnection', url?: string | null } | null, lambda?: { __typename?: 'WorkbenchToolLambdaConnection', lambdaArn?: string | null, description?: string | null, inputSchema?: Record | null } | null, cloudRun?: { __typename?: 'WorkbenchToolCloudRunConnection', identifier?: string | null, description?: string | null, inputSchema?: Record | null } | null, azureFunction?: { __typename?: 'WorkbenchToolAzureFunctionConnection', identifier?: string | null, description?: string | null, inputSchema?: Record | null } | null, docker?: { __typename?: 'WorkbenchToolDockerConnection', url?: string | null, provider?: HelmAuthProvider | null, proxy?: { __typename?: 'HttpProxyConfiguration', url: string, noproxy?: string | null } | null } | null } | null, cloudConnection?: { __typename?: 'CloudConnection', id: string, name: string, provider: Provider } | null, mcpServer?: { __typename?: 'McpServer', id: string, name: string, url: string } | null } | null> | null, readBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, writeBindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, botUser?: { __typename?: 'User', id: string, name: string, email: string, profile?: string | null } | null, webhooks?: { __typename?: 'WorkbenchWebhookConnection', edges?: Array<{ __typename?: 'WorkbenchWebhookEdge', node?: { __typename?: 'WorkbenchWebhook', id: string, name?: string | null, priority?: number | null, webhook?: { __typename?: 'ObservabilityWebhook', id: string, type: ObservabilityWebhookType } | null, issueWebhook?: { __typename?: 'IssueWebhook', id: string, provider: IssueWebhookProvider } | null } | null } | null> | null } | null } | null };
export type UpdateWorkbenchKnowledgeMutationVariables = Exact<{
id: Scalars['ID']['input'];
@@ -29035,6 +29041,7 @@ export const WorkbenchFragmentDoc = gql`
id
}
configuration {
+ selfService
infrastructure {
services
stacks
diff --git a/js/console/src/generated/persisted-queries/client.json b/js/console/src/generated/persisted-queries/client.json
index 5ccd5ece4d..8ac4bc2358 100644
--- a/js/console/src/generated/persisted-queries/client.json
+++ b/js/console/src/generated/persisted-queries/client.json
@@ -1977,10 +1977,10 @@
"name": "WorkbenchesAlerts",
"body": "query WorkbenchesAlerts($first: Int = 100, $after: String) {\n workbenchAlerts(first: $first, after: $after) {\n pageInfo {\n ...PageInfo\n __typename\n }\n edges {\n node {\n ...Alert\n __typename\n }\n __typename\n }\n __typename\n }\n}\n\nfragment PageInfo on PageInfo {\n hasNextPage\n endCursor\n hasPreviousPage\n startCursor\n __typename\n}\n\nfragment Alert on Alert {\n id\n title\n message\n type\n severity\n state\n fingerprint\n url\n annotations\n tags {\n id\n name\n value\n __typename\n }\n insight {\n ...AiInsight\n __typename\n }\n resolution {\n ...AlertResolution\n __typename\n }\n workbench {\n id\n __typename\n }\n workbenchJob {\n id\n status\n __typename\n }\n updatedAt\n __typename\n}\n\nfragment AiInsight on AiInsight {\n id\n text\n summary\n sha\n freshness\n updatedAt\n insertedAt\n error {\n message\n source\n __typename\n }\n ...AiInsightContext\n __typename\n}\n\nfragment AiInsightContext on AiInsight {\n evidence {\n ...AiInsightEvidence\n __typename\n }\n cluster {\n id\n name\n distro\n provider {\n cloud\n __typename\n }\n __typename\n }\n clusterInsightComponent {\n id\n group\n version\n kind\n name\n namespace\n cluster {\n ...ClusterMinimal\n __typename\n }\n __typename\n }\n service {\n id\n name\n cluster {\n ...ClusterMinimal\n __typename\n }\n __typename\n }\n serviceComponent {\n id\n group\n version\n kind\n name\n namespace\n service {\n id\n name\n cluster {\n ...ClusterMinimal\n __typename\n }\n __typename\n }\n __typename\n }\n stack {\n id\n name\n type\n __typename\n }\n stackRun {\n id\n message\n type\n stack {\n id\n name\n __typename\n }\n __typename\n }\n alert {\n id\n title\n message\n __typename\n }\n __typename\n}\n\nfragment AiInsightEvidence on AiInsightEvidence {\n id\n type\n logs {\n ...LogsEvidence\n __typename\n }\n pullRequest {\n ...PullRequestEvidence\n __typename\n }\n alert {\n ...AlertEvidence\n __typename\n }\n knowledge {\n ...KnowledgeEvidence\n __typename\n }\n insertedAt\n updatedAt\n __typename\n}\n\nfragment LogsEvidence on LogsEvidence {\n clusterId\n serviceId\n line\n lines {\n ...LogLine\n __typename\n }\n __typename\n}\n\nfragment LogLine on LogLine {\n facets {\n ...LogFacet\n __typename\n }\n log\n timestamp\n __typename\n}\n\nfragment LogFacet on LogFacet {\n key\n value\n __typename\n}\n\nfragment PullRequestEvidence on PullRequestEvidence {\n contents\n filename\n patch\n repo\n sha\n title\n url\n __typename\n}\n\nfragment AlertEvidence on AlertEvidence {\n alertId\n title\n resolution\n __typename\n}\n\nfragment KnowledgeEvidence on KnowledgeEvidence {\n name\n observations\n type\n __typename\n}\n\nfragment ClusterMinimal on Cluster {\n id\n name\n handle\n provider {\n name\n cloud\n __typename\n }\n distro\n __typename\n}\n\nfragment AlertResolution on AlertResolution {\n resolution\n __typename\n}"
},
- "sha256:2c415431a394597ae3c5098ce513eaf76102fc4824deaecbfd069b9853dce39b": {
+ "sha256:53d698fb0eba485da82d62cbeb9c5baa944e6daf6b04fab13b73f2e710913aca": {
"type": "query",
"name": "Workbench",
- "body": "query Workbench($id: ID, $name: String) {\n workbench(id: $id, name: $name) {\n ...Workbench\n __typename\n }\n}\n\nfragment Workbench on Workbench {\n ...WorkbenchTiny\n systemPrompt\n agentRuntime {\n id\n name\n allowedRepositories\n __typename\n }\n repository {\n id\n __typename\n }\n configuration {\n infrastructure {\n services\n stacks\n kubernetes\n podLogs\n vulnerabilities\n sentinels\n __typename\n }\n observability {\n logs\n metrics\n __typename\n }\n coding {\n mode\n repositories\n enableBabysitting\n __typename\n }\n __typename\n }\n modes {\n ...WorkbenchJobModesFields\n __typename\n }\n budget {\n enabled\n maximum\n minFree\n unit\n last\n lastUpdated\n __typename\n }\n skills {\n ref {\n ref\n folder\n __typename\n }\n files\n __typename\n }\n workbenchSkills(first: 500) {\n edges {\n node {\n id\n name\n description\n contents\n subagents\n __typename\n }\n __typename\n }\n __typename\n }\n workbenchKnowledge(first: 50) {\n edges {\n node {\n id\n name\n description\n knowledge\n labels\n usages\n lastUsedAt\n __typename\n }\n __typename\n }\n __typename\n }\n tools {\n ...WorkbenchTool\n __typename\n }\n readBindings {\n ...PolicyBinding\n __typename\n }\n writeBindings {\n ...PolicyBinding\n __typename\n }\n botUser {\n id\n name\n email\n profile\n __typename\n }\n __typename\n}\n\nfragment WorkbenchTiny on Workbench {\n id\n name\n description\n agentRuntime {\n id\n name\n type\n __typename\n }\n tools {\n ...WorkbenchToolTiny\n __typename\n }\n webhooks(first: 50) {\n edges {\n node {\n ...WorkbenchWebhookTiny\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n}\n\nfragment WorkbenchToolTiny on WorkbenchTool {\n id\n name\n tool\n categories\n approval\n cloudConnection {\n ...CloudConnectionTiny\n __typename\n }\n mcpServer {\n id\n name\n url\n __typename\n }\n __typename\n}\n\nfragment CloudConnectionTiny on CloudConnection {\n id\n name\n provider\n __typename\n}\n\nfragment WorkbenchWebhookTiny on WorkbenchWebhook {\n id\n name\n priority\n webhook {\n id\n type\n __typename\n }\n issueWebhook {\n ...IssueWebhookTiny\n __typename\n }\n __typename\n}\n\nfragment IssueWebhookTiny on IssueWebhook {\n id\n provider\n __typename\n}\n\nfragment WorkbenchJobModesFields on WorkbenchJobModes {\n plan\n verification\n model {\n provider\n model\n __typename\n }\n coding {\n approval\n babysit\n review\n __typename\n }\n budget {\n cost\n tokens\n __typename\n }\n kubernetes {\n update\n delete\n exec\n drain\n excludeNamespaces\n requireNamespaces\n __typename\n }\n __typename\n}\n\nfragment WorkbenchTool on WorkbenchTool {\n ...WorkbenchToolTiny\n scmConnection {\n id\n name\n type\n __typename\n }\n readBindings {\n ...PolicyBinding\n __typename\n }\n writeBindings {\n ...PolicyBinding\n __typename\n }\n configuration {\n ...WorkbenchToolConfigurationFields\n __typename\n }\n __typename\n}\n\nfragment PolicyBinding on PolicyBinding {\n id\n user {\n id\n name\n email\n __typename\n }\n group {\n id\n name\n __typename\n }\n __typename\n}\n\nfragment WorkbenchToolConfigurationFields on WorkbenchToolConfiguration {\n http {\n url\n method\n headers {\n name\n value\n __typename\n }\n body\n inputSchema\n __typename\n }\n datadog {\n site\n __typename\n }\n elastic {\n index\n url\n username\n __typename\n }\n opensearch {\n host\n index\n awsAccessKeyId\n awsRegion\n assumeRoleArn\n usePodIdentity\n __typename\n }\n loki {\n url\n username\n tenantId\n __typename\n }\n victoriaLogs {\n url\n username\n accountId\n projectId\n __typename\n }\n prometheus {\n url\n username\n tenantId\n awsSigv4\n awsAccessKeyId\n awsRegion\n __typename\n }\n tempo {\n url\n username\n tenantId\n __typename\n }\n jaeger {\n url\n username\n __typename\n }\n atlassian {\n email\n url\n __typename\n }\n jira {\n email\n url\n __typename\n }\n jiraDatacenter {\n url\n __typename\n }\n linear {\n url\n __typename\n }\n slack {\n url\n __typename\n }\n pagerduty {\n url\n __typename\n }\n teams {\n clientId\n tenantId\n __typename\n }\n splunk {\n url\n tokenType\n username\n __typename\n }\n cloudwatch {\n logGroupNames\n region\n roleArn\n roleSessionName\n __typename\n }\n azure {\n subscriptionId\n tenantId\n clientId\n prometheusUrl\n __typename\n }\n dynatrace {\n url\n __typename\n }\n sentry {\n url\n __typename\n }\n github {\n url\n toolset\n appId\n installationId\n __typename\n }\n gitlab {\n url\n __typename\n }\n bitbucket {\n url\n __typename\n }\n bitbucketDatacenter {\n url\n __typename\n }\n azureDevops {\n url\n __typename\n }\n lambda {\n lambdaArn\n description\n inputSchema\n __typename\n }\n cloudRun {\n identifier\n description\n inputSchema\n __typename\n }\n azureFunction {\n identifier\n description\n inputSchema\n __typename\n }\n docker {\n url\n provider\n proxy {\n url\n noproxy\n __typename\n }\n __typename\n }\n __typename\n}"
+ "body": "query Workbench($id: ID, $name: String) {\n workbench(id: $id, name: $name) {\n ...Workbench\n __typename\n }\n}\n\nfragment Workbench on Workbench {\n ...WorkbenchTiny\n systemPrompt\n agentRuntime {\n id\n name\n allowedRepositories\n __typename\n }\n repository {\n id\n __typename\n }\n configuration {\n selfService\n infrastructure {\n services\n stacks\n kubernetes\n podLogs\n vulnerabilities\n sentinels\n __typename\n }\n observability {\n logs\n metrics\n __typename\n }\n coding {\n mode\n repositories\n enableBabysitting\n __typename\n }\n __typename\n }\n modes {\n ...WorkbenchJobModesFields\n __typename\n }\n budget {\n enabled\n maximum\n minFree\n unit\n last\n lastUpdated\n __typename\n }\n skills {\n ref {\n ref\n folder\n __typename\n }\n files\n __typename\n }\n workbenchSkills(first: 500) {\n edges {\n node {\n id\n name\n description\n contents\n subagents\n __typename\n }\n __typename\n }\n __typename\n }\n workbenchKnowledge(first: 50) {\n edges {\n node {\n id\n name\n description\n knowledge\n labels\n usages\n lastUsedAt\n __typename\n }\n __typename\n }\n __typename\n }\n tools {\n ...WorkbenchTool\n __typename\n }\n readBindings {\n ...PolicyBinding\n __typename\n }\n writeBindings {\n ...PolicyBinding\n __typename\n }\n botUser {\n id\n name\n email\n profile\n __typename\n }\n __typename\n}\n\nfragment WorkbenchTiny on Workbench {\n id\n name\n description\n agentRuntime {\n id\n name\n type\n __typename\n }\n tools {\n ...WorkbenchToolTiny\n __typename\n }\n webhooks(first: 50) {\n edges {\n node {\n ...WorkbenchWebhookTiny\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n}\n\nfragment WorkbenchToolTiny on WorkbenchTool {\n id\n name\n tool\n categories\n approval\n cloudConnection {\n ...CloudConnectionTiny\n __typename\n }\n mcpServer {\n id\n name\n url\n __typename\n }\n __typename\n}\n\nfragment CloudConnectionTiny on CloudConnection {\n id\n name\n provider\n __typename\n}\n\nfragment WorkbenchWebhookTiny on WorkbenchWebhook {\n id\n name\n priority\n webhook {\n id\n type\n __typename\n }\n issueWebhook {\n ...IssueWebhookTiny\n __typename\n }\n __typename\n}\n\nfragment IssueWebhookTiny on IssueWebhook {\n id\n provider\n __typename\n}\n\nfragment WorkbenchJobModesFields on WorkbenchJobModes {\n plan\n verification\n model {\n provider\n model\n __typename\n }\n coding {\n approval\n babysit\n review\n __typename\n }\n budget {\n cost\n tokens\n __typename\n }\n kubernetes {\n update\n delete\n exec\n drain\n excludeNamespaces\n requireNamespaces\n __typename\n }\n __typename\n}\n\nfragment WorkbenchTool on WorkbenchTool {\n ...WorkbenchToolTiny\n scmConnection {\n id\n name\n type\n __typename\n }\n readBindings {\n ...PolicyBinding\n __typename\n }\n writeBindings {\n ...PolicyBinding\n __typename\n }\n configuration {\n ...WorkbenchToolConfigurationFields\n __typename\n }\n __typename\n}\n\nfragment PolicyBinding on PolicyBinding {\n id\n user {\n id\n name\n email\n __typename\n }\n group {\n id\n name\n __typename\n }\n __typename\n}\n\nfragment WorkbenchToolConfigurationFields on WorkbenchToolConfiguration {\n http {\n url\n method\n headers {\n name\n value\n __typename\n }\n body\n inputSchema\n __typename\n }\n datadog {\n site\n __typename\n }\n elastic {\n index\n url\n username\n __typename\n }\n opensearch {\n host\n index\n awsAccessKeyId\n awsRegion\n assumeRoleArn\n usePodIdentity\n __typename\n }\n loki {\n url\n username\n tenantId\n __typename\n }\n victoriaLogs {\n url\n username\n accountId\n projectId\n __typename\n }\n prometheus {\n url\n username\n tenantId\n awsSigv4\n awsAccessKeyId\n awsRegion\n __typename\n }\n tempo {\n url\n username\n tenantId\n __typename\n }\n jaeger {\n url\n username\n __typename\n }\n atlassian {\n email\n url\n __typename\n }\n jira {\n email\n url\n __typename\n }\n jiraDatacenter {\n url\n __typename\n }\n linear {\n url\n __typename\n }\n slack {\n url\n __typename\n }\n pagerduty {\n url\n __typename\n }\n teams {\n clientId\n tenantId\n __typename\n }\n splunk {\n url\n tokenType\n username\n __typename\n }\n cloudwatch {\n logGroupNames\n region\n roleArn\n roleSessionName\n __typename\n }\n azure {\n subscriptionId\n tenantId\n clientId\n prometheusUrl\n __typename\n }\n dynatrace {\n url\n __typename\n }\n sentry {\n url\n __typename\n }\n github {\n url\n toolset\n appId\n installationId\n __typename\n }\n gitlab {\n url\n __typename\n }\n bitbucket {\n url\n __typename\n }\n bitbucketDatacenter {\n url\n __typename\n }\n azureDevops {\n url\n __typename\n }\n lambda {\n lambdaArn\n description\n inputSchema\n __typename\n }\n cloudRun {\n identifier\n description\n inputSchema\n __typename\n }\n azureFunction {\n identifier\n description\n inputSchema\n __typename\n }\n docker {\n url\n provider\n proxy {\n url\n noproxy\n __typename\n }\n __typename\n }\n __typename\n}"
},
"sha256:6c3686838d1372371451664e8d6b593929eeca76e340065ed6dda5691e325b56": {
"type": "query",
@@ -2172,15 +2172,15 @@
"name": "WorkbenchTool",
"body": "query WorkbenchTool($id: ID, $name: String) {\n workbenchTool(id: $id, name: $name) {\n ...WorkbenchTool\n __typename\n }\n}\n\nfragment WorkbenchTool on WorkbenchTool {\n ...WorkbenchToolTiny\n scmConnection {\n id\n name\n type\n __typename\n }\n readBindings {\n ...PolicyBinding\n __typename\n }\n writeBindings {\n ...PolicyBinding\n __typename\n }\n configuration {\n ...WorkbenchToolConfigurationFields\n __typename\n }\n __typename\n}\n\nfragment WorkbenchToolTiny on WorkbenchTool {\n id\n name\n tool\n categories\n approval\n cloudConnection {\n ...CloudConnectionTiny\n __typename\n }\n mcpServer {\n id\n name\n url\n __typename\n }\n __typename\n}\n\nfragment CloudConnectionTiny on CloudConnection {\n id\n name\n provider\n __typename\n}\n\nfragment PolicyBinding on PolicyBinding {\n id\n user {\n id\n name\n email\n __typename\n }\n group {\n id\n name\n __typename\n }\n __typename\n}\n\nfragment WorkbenchToolConfigurationFields on WorkbenchToolConfiguration {\n http {\n url\n method\n headers {\n name\n value\n __typename\n }\n body\n inputSchema\n __typename\n }\n datadog {\n site\n __typename\n }\n elastic {\n index\n url\n username\n __typename\n }\n opensearch {\n host\n index\n awsAccessKeyId\n awsRegion\n assumeRoleArn\n usePodIdentity\n __typename\n }\n loki {\n url\n username\n tenantId\n __typename\n }\n victoriaLogs {\n url\n username\n accountId\n projectId\n __typename\n }\n prometheus {\n url\n username\n tenantId\n awsSigv4\n awsAccessKeyId\n awsRegion\n __typename\n }\n tempo {\n url\n username\n tenantId\n __typename\n }\n jaeger {\n url\n username\n __typename\n }\n atlassian {\n email\n url\n __typename\n }\n jira {\n email\n url\n __typename\n }\n jiraDatacenter {\n url\n __typename\n }\n linear {\n url\n __typename\n }\n slack {\n url\n __typename\n }\n pagerduty {\n url\n __typename\n }\n teams {\n clientId\n tenantId\n __typename\n }\n splunk {\n url\n tokenType\n username\n __typename\n }\n cloudwatch {\n logGroupNames\n region\n roleArn\n roleSessionName\n __typename\n }\n azure {\n subscriptionId\n tenantId\n clientId\n prometheusUrl\n __typename\n }\n dynatrace {\n url\n __typename\n }\n sentry {\n url\n __typename\n }\n github {\n url\n toolset\n appId\n installationId\n __typename\n }\n gitlab {\n url\n __typename\n }\n bitbucket {\n url\n __typename\n }\n bitbucketDatacenter {\n url\n __typename\n }\n azureDevops {\n url\n __typename\n }\n lambda {\n lambdaArn\n description\n inputSchema\n __typename\n }\n cloudRun {\n identifier\n description\n inputSchema\n __typename\n }\n azureFunction {\n identifier\n description\n inputSchema\n __typename\n }\n docker {\n url\n provider\n proxy {\n url\n noproxy\n __typename\n }\n __typename\n }\n __typename\n}"
},
- "sha256:a9eb8b41c9dc3fec5612b1e833623019732a792c9a7f40783e29196c82768a2b": {
+ "sha256:5817da15d0e9f304edbf3f370b7d8fe18b30fef0fe71897793f63e096bf06b70": {
"type": "mutation",
"name": "CreateWorkbench",
- "body": "mutation CreateWorkbench($attributes: WorkbenchAttributes!) {\n createWorkbench(attributes: $attributes) {\n ...Workbench\n __typename\n }\n}\n\nfragment Workbench on Workbench {\n ...WorkbenchTiny\n systemPrompt\n agentRuntime {\n id\n name\n allowedRepositories\n __typename\n }\n repository {\n id\n __typename\n }\n configuration {\n infrastructure {\n services\n stacks\n kubernetes\n podLogs\n vulnerabilities\n sentinels\n __typename\n }\n observability {\n logs\n metrics\n __typename\n }\n coding {\n mode\n repositories\n enableBabysitting\n __typename\n }\n __typename\n }\n modes {\n ...WorkbenchJobModesFields\n __typename\n }\n budget {\n enabled\n maximum\n minFree\n unit\n last\n lastUpdated\n __typename\n }\n skills {\n ref {\n ref\n folder\n __typename\n }\n files\n __typename\n }\n workbenchSkills(first: 500) {\n edges {\n node {\n id\n name\n description\n contents\n subagents\n __typename\n }\n __typename\n }\n __typename\n }\n workbenchKnowledge(first: 50) {\n edges {\n node {\n id\n name\n description\n knowledge\n labels\n usages\n lastUsedAt\n __typename\n }\n __typename\n }\n __typename\n }\n tools {\n ...WorkbenchTool\n __typename\n }\n readBindings {\n ...PolicyBinding\n __typename\n }\n writeBindings {\n ...PolicyBinding\n __typename\n }\n botUser {\n id\n name\n email\n profile\n __typename\n }\n __typename\n}\n\nfragment WorkbenchTiny on Workbench {\n id\n name\n description\n agentRuntime {\n id\n name\n type\n __typename\n }\n tools {\n ...WorkbenchToolTiny\n __typename\n }\n webhooks(first: 50) {\n edges {\n node {\n ...WorkbenchWebhookTiny\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n}\n\nfragment WorkbenchToolTiny on WorkbenchTool {\n id\n name\n tool\n categories\n approval\n cloudConnection {\n ...CloudConnectionTiny\n __typename\n }\n mcpServer {\n id\n name\n url\n __typename\n }\n __typename\n}\n\nfragment CloudConnectionTiny on CloudConnection {\n id\n name\n provider\n __typename\n}\n\nfragment WorkbenchWebhookTiny on WorkbenchWebhook {\n id\n name\n priority\n webhook {\n id\n type\n __typename\n }\n issueWebhook {\n ...IssueWebhookTiny\n __typename\n }\n __typename\n}\n\nfragment IssueWebhookTiny on IssueWebhook {\n id\n provider\n __typename\n}\n\nfragment WorkbenchJobModesFields on WorkbenchJobModes {\n plan\n verification\n model {\n provider\n model\n __typename\n }\n coding {\n approval\n babysit\n review\n __typename\n }\n budget {\n cost\n tokens\n __typename\n }\n kubernetes {\n update\n delete\n exec\n drain\n excludeNamespaces\n requireNamespaces\n __typename\n }\n __typename\n}\n\nfragment WorkbenchTool on WorkbenchTool {\n ...WorkbenchToolTiny\n scmConnection {\n id\n name\n type\n __typename\n }\n readBindings {\n ...PolicyBinding\n __typename\n }\n writeBindings {\n ...PolicyBinding\n __typename\n }\n configuration {\n ...WorkbenchToolConfigurationFields\n __typename\n }\n __typename\n}\n\nfragment PolicyBinding on PolicyBinding {\n id\n user {\n id\n name\n email\n __typename\n }\n group {\n id\n name\n __typename\n }\n __typename\n}\n\nfragment WorkbenchToolConfigurationFields on WorkbenchToolConfiguration {\n http {\n url\n method\n headers {\n name\n value\n __typename\n }\n body\n inputSchema\n __typename\n }\n datadog {\n site\n __typename\n }\n elastic {\n index\n url\n username\n __typename\n }\n opensearch {\n host\n index\n awsAccessKeyId\n awsRegion\n assumeRoleArn\n usePodIdentity\n __typename\n }\n loki {\n url\n username\n tenantId\n __typename\n }\n victoriaLogs {\n url\n username\n accountId\n projectId\n __typename\n }\n prometheus {\n url\n username\n tenantId\n awsSigv4\n awsAccessKeyId\n awsRegion\n __typename\n }\n tempo {\n url\n username\n tenantId\n __typename\n }\n jaeger {\n url\n username\n __typename\n }\n atlassian {\n email\n url\n __typename\n }\n jira {\n email\n url\n __typename\n }\n jiraDatacenter {\n url\n __typename\n }\n linear {\n url\n __typename\n }\n slack {\n url\n __typename\n }\n pagerduty {\n url\n __typename\n }\n teams {\n clientId\n tenantId\n __typename\n }\n splunk {\n url\n tokenType\n username\n __typename\n }\n cloudwatch {\n logGroupNames\n region\n roleArn\n roleSessionName\n __typename\n }\n azure {\n subscriptionId\n tenantId\n clientId\n prometheusUrl\n __typename\n }\n dynatrace {\n url\n __typename\n }\n sentry {\n url\n __typename\n }\n github {\n url\n toolset\n appId\n installationId\n __typename\n }\n gitlab {\n url\n __typename\n }\n bitbucket {\n url\n __typename\n }\n bitbucketDatacenter {\n url\n __typename\n }\n azureDevops {\n url\n __typename\n }\n lambda {\n lambdaArn\n description\n inputSchema\n __typename\n }\n cloudRun {\n identifier\n description\n inputSchema\n __typename\n }\n azureFunction {\n identifier\n description\n inputSchema\n __typename\n }\n docker {\n url\n provider\n proxy {\n url\n noproxy\n __typename\n }\n __typename\n }\n __typename\n}"
+ "body": "mutation CreateWorkbench($attributes: WorkbenchAttributes!) {\n createWorkbench(attributes: $attributes) {\n ...Workbench\n __typename\n }\n}\n\nfragment Workbench on Workbench {\n ...WorkbenchTiny\n systemPrompt\n agentRuntime {\n id\n name\n allowedRepositories\n __typename\n }\n repository {\n id\n __typename\n }\n configuration {\n selfService\n infrastructure {\n services\n stacks\n kubernetes\n podLogs\n vulnerabilities\n sentinels\n __typename\n }\n observability {\n logs\n metrics\n __typename\n }\n coding {\n mode\n repositories\n enableBabysitting\n __typename\n }\n __typename\n }\n modes {\n ...WorkbenchJobModesFields\n __typename\n }\n budget {\n enabled\n maximum\n minFree\n unit\n last\n lastUpdated\n __typename\n }\n skills {\n ref {\n ref\n folder\n __typename\n }\n files\n __typename\n }\n workbenchSkills(first: 500) {\n edges {\n node {\n id\n name\n description\n contents\n subagents\n __typename\n }\n __typename\n }\n __typename\n }\n workbenchKnowledge(first: 50) {\n edges {\n node {\n id\n name\n description\n knowledge\n labels\n usages\n lastUsedAt\n __typename\n }\n __typename\n }\n __typename\n }\n tools {\n ...WorkbenchTool\n __typename\n }\n readBindings {\n ...PolicyBinding\n __typename\n }\n writeBindings {\n ...PolicyBinding\n __typename\n }\n botUser {\n id\n name\n email\n profile\n __typename\n }\n __typename\n}\n\nfragment WorkbenchTiny on Workbench {\n id\n name\n description\n agentRuntime {\n id\n name\n type\n __typename\n }\n tools {\n ...WorkbenchToolTiny\n __typename\n }\n webhooks(first: 50) {\n edges {\n node {\n ...WorkbenchWebhookTiny\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n}\n\nfragment WorkbenchToolTiny on WorkbenchTool {\n id\n name\n tool\n categories\n approval\n cloudConnection {\n ...CloudConnectionTiny\n __typename\n }\n mcpServer {\n id\n name\n url\n __typename\n }\n __typename\n}\n\nfragment CloudConnectionTiny on CloudConnection {\n id\n name\n provider\n __typename\n}\n\nfragment WorkbenchWebhookTiny on WorkbenchWebhook {\n id\n name\n priority\n webhook {\n id\n type\n __typename\n }\n issueWebhook {\n ...IssueWebhookTiny\n __typename\n }\n __typename\n}\n\nfragment IssueWebhookTiny on IssueWebhook {\n id\n provider\n __typename\n}\n\nfragment WorkbenchJobModesFields on WorkbenchJobModes {\n plan\n verification\n model {\n provider\n model\n __typename\n }\n coding {\n approval\n babysit\n review\n __typename\n }\n budget {\n cost\n tokens\n __typename\n }\n kubernetes {\n update\n delete\n exec\n drain\n excludeNamespaces\n requireNamespaces\n __typename\n }\n __typename\n}\n\nfragment WorkbenchTool on WorkbenchTool {\n ...WorkbenchToolTiny\n scmConnection {\n id\n name\n type\n __typename\n }\n readBindings {\n ...PolicyBinding\n __typename\n }\n writeBindings {\n ...PolicyBinding\n __typename\n }\n configuration {\n ...WorkbenchToolConfigurationFields\n __typename\n }\n __typename\n}\n\nfragment PolicyBinding on PolicyBinding {\n id\n user {\n id\n name\n email\n __typename\n }\n group {\n id\n name\n __typename\n }\n __typename\n}\n\nfragment WorkbenchToolConfigurationFields on WorkbenchToolConfiguration {\n http {\n url\n method\n headers {\n name\n value\n __typename\n }\n body\n inputSchema\n __typename\n }\n datadog {\n site\n __typename\n }\n elastic {\n index\n url\n username\n __typename\n }\n opensearch {\n host\n index\n awsAccessKeyId\n awsRegion\n assumeRoleArn\n usePodIdentity\n __typename\n }\n loki {\n url\n username\n tenantId\n __typename\n }\n victoriaLogs {\n url\n username\n accountId\n projectId\n __typename\n }\n prometheus {\n url\n username\n tenantId\n awsSigv4\n awsAccessKeyId\n awsRegion\n __typename\n }\n tempo {\n url\n username\n tenantId\n __typename\n }\n jaeger {\n url\n username\n __typename\n }\n atlassian {\n email\n url\n __typename\n }\n jira {\n email\n url\n __typename\n }\n jiraDatacenter {\n url\n __typename\n }\n linear {\n url\n __typename\n }\n slack {\n url\n __typename\n }\n pagerduty {\n url\n __typename\n }\n teams {\n clientId\n tenantId\n __typename\n }\n splunk {\n url\n tokenType\n username\n __typename\n }\n cloudwatch {\n logGroupNames\n region\n roleArn\n roleSessionName\n __typename\n }\n azure {\n subscriptionId\n tenantId\n clientId\n prometheusUrl\n __typename\n }\n dynatrace {\n url\n __typename\n }\n sentry {\n url\n __typename\n }\n github {\n url\n toolset\n appId\n installationId\n __typename\n }\n gitlab {\n url\n __typename\n }\n bitbucket {\n url\n __typename\n }\n bitbucketDatacenter {\n url\n __typename\n }\n azureDevops {\n url\n __typename\n }\n lambda {\n lambdaArn\n description\n inputSchema\n __typename\n }\n cloudRun {\n identifier\n description\n inputSchema\n __typename\n }\n azureFunction {\n identifier\n description\n inputSchema\n __typename\n }\n docker {\n url\n provider\n proxy {\n url\n noproxy\n __typename\n }\n __typename\n }\n __typename\n}"
},
- "sha256:b6e1ba94a3fad89090914b8917d4006dc51293cab82c1f7cbe4cc2038014500c": {
+ "sha256:d6ccd95c827655d4c89b8e3bf6280bf7da71e2b8ff91810c24a445b061915b01": {
"type": "mutation",
"name": "UpdateWorkbench",
- "body": "mutation UpdateWorkbench($id: ID!, $attributes: WorkbenchAttributes!) {\n updateWorkbench(id: $id, attributes: $attributes) {\n ...Workbench\n __typename\n }\n}\n\nfragment Workbench on Workbench {\n ...WorkbenchTiny\n systemPrompt\n agentRuntime {\n id\n name\n allowedRepositories\n __typename\n }\n repository {\n id\n __typename\n }\n configuration {\n infrastructure {\n services\n stacks\n kubernetes\n podLogs\n vulnerabilities\n sentinels\n __typename\n }\n observability {\n logs\n metrics\n __typename\n }\n coding {\n mode\n repositories\n enableBabysitting\n __typename\n }\n __typename\n }\n modes {\n ...WorkbenchJobModesFields\n __typename\n }\n budget {\n enabled\n maximum\n minFree\n unit\n last\n lastUpdated\n __typename\n }\n skills {\n ref {\n ref\n folder\n __typename\n }\n files\n __typename\n }\n workbenchSkills(first: 500) {\n edges {\n node {\n id\n name\n description\n contents\n subagents\n __typename\n }\n __typename\n }\n __typename\n }\n workbenchKnowledge(first: 50) {\n edges {\n node {\n id\n name\n description\n knowledge\n labels\n usages\n lastUsedAt\n __typename\n }\n __typename\n }\n __typename\n }\n tools {\n ...WorkbenchTool\n __typename\n }\n readBindings {\n ...PolicyBinding\n __typename\n }\n writeBindings {\n ...PolicyBinding\n __typename\n }\n botUser {\n id\n name\n email\n profile\n __typename\n }\n __typename\n}\n\nfragment WorkbenchTiny on Workbench {\n id\n name\n description\n agentRuntime {\n id\n name\n type\n __typename\n }\n tools {\n ...WorkbenchToolTiny\n __typename\n }\n webhooks(first: 50) {\n edges {\n node {\n ...WorkbenchWebhookTiny\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n}\n\nfragment WorkbenchToolTiny on WorkbenchTool {\n id\n name\n tool\n categories\n approval\n cloudConnection {\n ...CloudConnectionTiny\n __typename\n }\n mcpServer {\n id\n name\n url\n __typename\n }\n __typename\n}\n\nfragment CloudConnectionTiny on CloudConnection {\n id\n name\n provider\n __typename\n}\n\nfragment WorkbenchWebhookTiny on WorkbenchWebhook {\n id\n name\n priority\n webhook {\n id\n type\n __typename\n }\n issueWebhook {\n ...IssueWebhookTiny\n __typename\n }\n __typename\n}\n\nfragment IssueWebhookTiny on IssueWebhook {\n id\n provider\n __typename\n}\n\nfragment WorkbenchJobModesFields on WorkbenchJobModes {\n plan\n verification\n model {\n provider\n model\n __typename\n }\n coding {\n approval\n babysit\n review\n __typename\n }\n budget {\n cost\n tokens\n __typename\n }\n kubernetes {\n update\n delete\n exec\n drain\n excludeNamespaces\n requireNamespaces\n __typename\n }\n __typename\n}\n\nfragment WorkbenchTool on WorkbenchTool {\n ...WorkbenchToolTiny\n scmConnection {\n id\n name\n type\n __typename\n }\n readBindings {\n ...PolicyBinding\n __typename\n }\n writeBindings {\n ...PolicyBinding\n __typename\n }\n configuration {\n ...WorkbenchToolConfigurationFields\n __typename\n }\n __typename\n}\n\nfragment PolicyBinding on PolicyBinding {\n id\n user {\n id\n name\n email\n __typename\n }\n group {\n id\n name\n __typename\n }\n __typename\n}\n\nfragment WorkbenchToolConfigurationFields on WorkbenchToolConfiguration {\n http {\n url\n method\n headers {\n name\n value\n __typename\n }\n body\n inputSchema\n __typename\n }\n datadog {\n site\n __typename\n }\n elastic {\n index\n url\n username\n __typename\n }\n opensearch {\n host\n index\n awsAccessKeyId\n awsRegion\n assumeRoleArn\n usePodIdentity\n __typename\n }\n loki {\n url\n username\n tenantId\n __typename\n }\n victoriaLogs {\n url\n username\n accountId\n projectId\n __typename\n }\n prometheus {\n url\n username\n tenantId\n awsSigv4\n awsAccessKeyId\n awsRegion\n __typename\n }\n tempo {\n url\n username\n tenantId\n __typename\n }\n jaeger {\n url\n username\n __typename\n }\n atlassian {\n email\n url\n __typename\n }\n jira {\n email\n url\n __typename\n }\n jiraDatacenter {\n url\n __typename\n }\n linear {\n url\n __typename\n }\n slack {\n url\n __typename\n }\n pagerduty {\n url\n __typename\n }\n teams {\n clientId\n tenantId\n __typename\n }\n splunk {\n url\n tokenType\n username\n __typename\n }\n cloudwatch {\n logGroupNames\n region\n roleArn\n roleSessionName\n __typename\n }\n azure {\n subscriptionId\n tenantId\n clientId\n prometheusUrl\n __typename\n }\n dynatrace {\n url\n __typename\n }\n sentry {\n url\n __typename\n }\n github {\n url\n toolset\n appId\n installationId\n __typename\n }\n gitlab {\n url\n __typename\n }\n bitbucket {\n url\n __typename\n }\n bitbucketDatacenter {\n url\n __typename\n }\n azureDevops {\n url\n __typename\n }\n lambda {\n lambdaArn\n description\n inputSchema\n __typename\n }\n cloudRun {\n identifier\n description\n inputSchema\n __typename\n }\n azureFunction {\n identifier\n description\n inputSchema\n __typename\n }\n docker {\n url\n provider\n proxy {\n url\n noproxy\n __typename\n }\n __typename\n }\n __typename\n}"
+ "body": "mutation UpdateWorkbench($id: ID!, $attributes: WorkbenchAttributes!) {\n updateWorkbench(id: $id, attributes: $attributes) {\n ...Workbench\n __typename\n }\n}\n\nfragment Workbench on Workbench {\n ...WorkbenchTiny\n systemPrompt\n agentRuntime {\n id\n name\n allowedRepositories\n __typename\n }\n repository {\n id\n __typename\n }\n configuration {\n selfService\n infrastructure {\n services\n stacks\n kubernetes\n podLogs\n vulnerabilities\n sentinels\n __typename\n }\n observability {\n logs\n metrics\n __typename\n }\n coding {\n mode\n repositories\n enableBabysitting\n __typename\n }\n __typename\n }\n modes {\n ...WorkbenchJobModesFields\n __typename\n }\n budget {\n enabled\n maximum\n minFree\n unit\n last\n lastUpdated\n __typename\n }\n skills {\n ref {\n ref\n folder\n __typename\n }\n files\n __typename\n }\n workbenchSkills(first: 500) {\n edges {\n node {\n id\n name\n description\n contents\n subagents\n __typename\n }\n __typename\n }\n __typename\n }\n workbenchKnowledge(first: 50) {\n edges {\n node {\n id\n name\n description\n knowledge\n labels\n usages\n lastUsedAt\n __typename\n }\n __typename\n }\n __typename\n }\n tools {\n ...WorkbenchTool\n __typename\n }\n readBindings {\n ...PolicyBinding\n __typename\n }\n writeBindings {\n ...PolicyBinding\n __typename\n }\n botUser {\n id\n name\n email\n profile\n __typename\n }\n __typename\n}\n\nfragment WorkbenchTiny on Workbench {\n id\n name\n description\n agentRuntime {\n id\n name\n type\n __typename\n }\n tools {\n ...WorkbenchToolTiny\n __typename\n }\n webhooks(first: 50) {\n edges {\n node {\n ...WorkbenchWebhookTiny\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n}\n\nfragment WorkbenchToolTiny on WorkbenchTool {\n id\n name\n tool\n categories\n approval\n cloudConnection {\n ...CloudConnectionTiny\n __typename\n }\n mcpServer {\n id\n name\n url\n __typename\n }\n __typename\n}\n\nfragment CloudConnectionTiny on CloudConnection {\n id\n name\n provider\n __typename\n}\n\nfragment WorkbenchWebhookTiny on WorkbenchWebhook {\n id\n name\n priority\n webhook {\n id\n type\n __typename\n }\n issueWebhook {\n ...IssueWebhookTiny\n __typename\n }\n __typename\n}\n\nfragment IssueWebhookTiny on IssueWebhook {\n id\n provider\n __typename\n}\n\nfragment WorkbenchJobModesFields on WorkbenchJobModes {\n plan\n verification\n model {\n provider\n model\n __typename\n }\n coding {\n approval\n babysit\n review\n __typename\n }\n budget {\n cost\n tokens\n __typename\n }\n kubernetes {\n update\n delete\n exec\n drain\n excludeNamespaces\n requireNamespaces\n __typename\n }\n __typename\n}\n\nfragment WorkbenchTool on WorkbenchTool {\n ...WorkbenchToolTiny\n scmConnection {\n id\n name\n type\n __typename\n }\n readBindings {\n ...PolicyBinding\n __typename\n }\n writeBindings {\n ...PolicyBinding\n __typename\n }\n configuration {\n ...WorkbenchToolConfigurationFields\n __typename\n }\n __typename\n}\n\nfragment PolicyBinding on PolicyBinding {\n id\n user {\n id\n name\n email\n __typename\n }\n group {\n id\n name\n __typename\n }\n __typename\n}\n\nfragment WorkbenchToolConfigurationFields on WorkbenchToolConfiguration {\n http {\n url\n method\n headers {\n name\n value\n __typename\n }\n body\n inputSchema\n __typename\n }\n datadog {\n site\n __typename\n }\n elastic {\n index\n url\n username\n __typename\n }\n opensearch {\n host\n index\n awsAccessKeyId\n awsRegion\n assumeRoleArn\n usePodIdentity\n __typename\n }\n loki {\n url\n username\n tenantId\n __typename\n }\n victoriaLogs {\n url\n username\n accountId\n projectId\n __typename\n }\n prometheus {\n url\n username\n tenantId\n awsSigv4\n awsAccessKeyId\n awsRegion\n __typename\n }\n tempo {\n url\n username\n tenantId\n __typename\n }\n jaeger {\n url\n username\n __typename\n }\n atlassian {\n email\n url\n __typename\n }\n jira {\n email\n url\n __typename\n }\n jiraDatacenter {\n url\n __typename\n }\n linear {\n url\n __typename\n }\n slack {\n url\n __typename\n }\n pagerduty {\n url\n __typename\n }\n teams {\n clientId\n tenantId\n __typename\n }\n splunk {\n url\n tokenType\n username\n __typename\n }\n cloudwatch {\n logGroupNames\n region\n roleArn\n roleSessionName\n __typename\n }\n azure {\n subscriptionId\n tenantId\n clientId\n prometheusUrl\n __typename\n }\n dynatrace {\n url\n __typename\n }\n sentry {\n url\n __typename\n }\n github {\n url\n toolset\n appId\n installationId\n __typename\n }\n gitlab {\n url\n __typename\n }\n bitbucket {\n url\n __typename\n }\n bitbucketDatacenter {\n url\n __typename\n }\n azureDevops {\n url\n __typename\n }\n lambda {\n lambdaArn\n description\n inputSchema\n __typename\n }\n cloudRun {\n identifier\n description\n inputSchema\n __typename\n }\n azureFunction {\n identifier\n description\n inputSchema\n __typename\n }\n docker {\n url\n provider\n proxy {\n url\n noproxy\n __typename\n }\n __typename\n }\n __typename\n}"
},
"sha256:9d48f13216f613d1a0265a4c8453d9ac1dfe8a3f75e1875a63d591c76afee930": {
"type": "mutation",
diff --git a/js/console/src/graph/workbench.graphql b/js/console/src/graph/workbench.graphql
index e56681aed7..912c0a103e 100644
--- a/js/console/src/graph/workbench.graphql
+++ b/js/console/src/graph/workbench.graphql
@@ -90,6 +90,7 @@ fragment Workbench on Workbench {
id
}
configuration {
+ selfService
infrastructure {
services
stacks
diff --git a/lib/console/ai/tools/workbench/self_service/catalog_search.ex b/lib/console/ai/tools/workbench/self_service/catalog_search.ex
new file mode 100644
index 0000000000..6bb265462a
--- /dev/null
+++ b/lib/console/ai/tools/workbench/self_service/catalog_search.ex
@@ -0,0 +1,91 @@
+defmodule Console.AI.Tools.Workbench.SelfService.CatalogSearch do
+ use Console.AI.Tools.Workbench.Base
+ import Ecto.Query
+ alias Console.Repo
+ alias Console.AI.Tool
+ alias Console.Deployments.{Git, Policies}
+ alias Console.Schema.{Catalog, PrAutomation}
+
+ embedded_schema do
+ field :query, :string
+ end
+
+ @valid ~w(query)a
+ @json_schema Console.priv_file!("tools/workbench/self_service/catalog_search.json") |> Jason.decode!()
+
+ def json_schema(), do: @json_schema
+ def name(), do: "workbench_catalog_search"
+ def description(), do: """
+ Search Plural catalogs and PR automations that are available to the current user.
+ Prefer this when you need a relevant golden path but do not yet know which catalog or automation fits.
+ Falls back to name search when semantic search is unavailable.
+ """
+
+ def changeset(model, attrs) do
+ model
+ |> cast(attrs, @valid)
+ |> validate_required([:query])
+ end
+
+ def implement(%__MODULE__{query: query}) do
+ with {:actor, %{} = user} <- {:actor, Tool.actor()},
+ {:search, ^user, {:ok, results}} <- {:search, user, Git.catalog_search(query, user: user, count: 100)} do
+ format_results(results)
+ else
+ {:actor, _} ->
+ {:ok, "not logged in"}
+ {:search, user, {:error, _}} ->
+ fallback_search(query, user)
+ end
+ end
+
+ defp fallback_search(query, user) do
+ catalog_hits(query, user)
+ |> Enum.concat(automation_hits(query, user))
+ |> Jason.encode()
+ end
+
+ defp catalog_hits(query, user) do
+ Catalog.search(query)
+ |> Catalog.for_user(user)
+ |> limit(100)
+ |> Repo.all()
+ |> Enum.map(&%{catalog: Map.take(&1, [:id, :name, :description, :category])})
+ end
+
+ defp automation_hits(query, user) do
+ PrAutomation.search(query)
+ |> limit(100)
+ |> Repo.all()
+ |> Repo.preload([:catalog])
+ |> Enum.filter(&readable?(&1, user))
+ |> Enum.map(fn pra ->
+ %{
+ pr_automation: Map.take(pra, [:id, :name, :documentation, :title, :branch])
+ |> Map.put(:description, pra.documentation)
+ |> Map.put(:catalog, pra.catalog && Map.take(pra.catalog, [:id, :name]))
+ }
+ end)
+ end
+
+ defp readable?(%PrAutomation{catalog: %Catalog{} = catalog}, user),
+ do: match?({:ok, _}, Policies.allow(catalog, user, :read))
+ defp readable?(%PrAutomation{} = pra, user),
+ do: match?({:ok, _}, Policies.allow(pra, user, :create))
+
+ defp format_results(results) do
+ Enum.map(results, fn
+ %{catalog: %Catalog{} = catalog} ->
+ %{catalog: Map.take(catalog, [:id, :name, :description, :category])}
+ %{pr_automation: %PrAutomation{} = pra} ->
+ %{
+ pr_automation:
+ Map.take(pra, [:id, :name, :documentation, :title, :branch])
+ |> Map.put(:description, pra.documentation)
+ }
+ other ->
+ other
+ end)
+ |> Jason.encode()
+ end
+end
diff --git a/lib/console/ai/tools/workbench/self_service/get_pr_automation.ex b/lib/console/ai/tools/workbench/self_service/get_pr_automation.ex
new file mode 100644
index 0000000000..863c92d80c
--- /dev/null
+++ b/lib/console/ai/tools/workbench/self_service/get_pr_automation.ex
@@ -0,0 +1,75 @@
+defmodule Console.AI.Tools.Workbench.SelfService.GetPrAutomation do
+ use Console.AI.Tools.Workbench.Base
+ alias Console.Repo
+ alias Console.AI.Tool
+ alias Console.Deployments.{Git, Policies}
+ alias Console.Schema.PrAutomation
+
+ embedded_schema do
+ field :pr_automation_id, :string
+ field :name, :string
+ end
+
+ @valid ~w(pr_automation_id name)a
+ @json_schema Console.priv_file!("tools/workbench/self_service/get_pr_automation.json") |> Jason.decode!()
+ @fields ~w(id name documentation title message branch branch_prefix identifier configuration icon dark_icon)a
+
+ def json_schema(), do: @json_schema
+ def name(), do: "workbench_get_pr_automation"
+ def description(), do: """
+ Fetch a single PR automation by id or name, including documentation, branch metadata,
+ configuration fields, and confirmation requirements. Use this before invoking an automation
+ so you can fill a valid context.
+ """
+
+ def changeset(model, attrs) do
+ model
+ |> cast(attrs, @valid)
+ |> validate_one_of()
+ end
+
+ defp validate_one_of(cs) do
+ case {get_field(cs, :pr_automation_id), get_field(cs, :name)} do
+ {id, _} when is_binary(id) and byte_size(id) > 0 -> cs
+ {_, name} when is_binary(name) and byte_size(name) > 0 -> cs
+ _ -> add_error(cs, :pr_automation_id, "either pr_automation_id or name is required")
+ end
+ end
+
+ def implement(%__MODULE__{} = model) do
+ with %{} = user <- Tool.actor(),
+ %PrAutomation{} = pra <- fetch(model),
+ {:ok, _} <- Policies.allow(pra, user, :read) do
+ pra
+ |> Repo.preload([:catalog])
+ |> format()
+ |> Jason.encode()
+ else
+ nil -> {:ok, "PR automation not found"}
+ {:error, _} -> {:ok, "You do not have access to this PR automation"}
+ _ -> {:ok, "not logged in"}
+ end
+ end
+
+ defp fetch(%__MODULE__{pr_automation_id: id}) when is_binary(id) and byte_size(id) > 0,
+ do: Git.get_pr_automation(id)
+ defp fetch(%__MODULE__{name: name}) when is_binary(name) and byte_size(name) > 0,
+ do: Git.get_pr_automation_by_name(name)
+ defp fetch(_), do: nil
+
+ defp format(%PrAutomation{} = pra) do
+ Map.take(pra, @fields)
+ |> Map.put(:description, pra.documentation)
+ |> Map.put(:catalog, format_catalog(pra.catalog))
+ |> Map.put(:confirmation, format_confirmation(pra.confirmation))
+ |> Console.mapify()
+ end
+
+ defp format_catalog(%{id: id, name: name, description: description, category: category}),
+ do: %{id: id, name: name, description: description, category: category}
+ defp format_catalog(_), do: nil
+
+ defp format_confirmation(%{text: text, checklist: checklist}),
+ do: %{text: text, checklist: Enum.map(checklist || [], &Map.take(&1, [:label]))}
+ defp format_confirmation(_), do: nil
+end
diff --git a/lib/console/ai/tools/workbench/self_service/invoke_pr_automation.ex b/lib/console/ai/tools/workbench/self_service/invoke_pr_automation.ex
new file mode 100644
index 0000000000..8f5b9ec81e
--- /dev/null
+++ b/lib/console/ai/tools/workbench/self_service/invoke_pr_automation.ex
@@ -0,0 +1,77 @@
+defmodule Console.AI.Tools.Workbench.SelfService.InvokePrAutomation do
+ use Console.AI.Tools.Workbench.Base
+ alias Console.AI.Tool
+ alias Console.Deployments.Git
+ alias Console.Schema.{WorkbenchJob, PullRequest}
+
+ embedded_schema do
+ field :pr_automation_id, :string
+ field :context, :string
+ field :branch, :string
+ field :identifier, :string
+ field :job, :map, virtual: true
+ end
+
+ @valid ~w(pr_automation_id context branch identifier)a
+ @json_schema Console.priv_file!("tools/workbench/self_service/invoke_pr_automation.json") |> Jason.decode!()
+
+ def json_schema(_), do: @json_schema
+ def name(_), do: "workbench_invoke_pr_automation"
+ def description(_), do: """
+ Invoke a PR automation to create a pull request for a clear GitOps provisioning pathway.
+ The generated pull request is automatically associated with the current workbench job.
+ Call this only after confirming a relevant automation and filling a valid context. Prefer a single invocation.
+ """
+
+ def changeset(model, attrs) do
+ model
+ |> cast(attrs, @valid)
+ |> validate_required([:pr_automation_id, :branch])
+ end
+
+ def implement(%__MODULE__{pr_automation_id: pra_id, branch: branch} = model) do
+ with %{} = user <- Tool.actor(),
+ %WorkbenchJob{id: job_id, workbench_id: workbench_id} <- job(model),
+ {:ok, %PullRequest{} = pr} <-
+ Git.create_pull_request(
+ %{workbench_job_id: job_id, workbench_id: workbench_id},
+ get_context(model),
+ pra_id,
+ branch,
+ model.identifier,
+ user
+ ) do
+ Jason.encode(%{
+ id: pr.id,
+ url: pr.url,
+ title: pr.title,
+ status: pr.status,
+ workbench_job_id: pr.workbench_job_id,
+ workbench_id: pr.workbench_id
+ })
+ else
+ nil -> {:ok, "no workbench job or user available for this invocation"}
+ {:error, %Ecto.Changeset{} = cs} ->
+ {:ok, "failed to create pull request: #{inspect(Console.GraphQl.Helpers.resolve_changeset(cs))}"}
+ {:error, err} when is_binary(err) -> {:ok, "failed to create pull request: #{err}"}
+ {:error, err} -> {:ok, "failed to create pull request: #{inspect(err)}"}
+ err -> {:ok, "failed to create pull request: #{inspect(err)}"}
+ end
+ end
+
+ defp job(%__MODULE__{job: %WorkbenchJob{} = job}), do: job
+ defp job(_) do
+ case Tool.context() do
+ %{job: %WorkbenchJob{} = job} -> job
+ _ -> nil
+ end
+ end
+
+ defp get_context(%__MODULE__{context: ctx}) when is_binary(ctx) do
+ case Jason.decode(ctx) do
+ {:ok, %{} = map} -> map
+ _ -> %{}
+ end
+ end
+ defp get_context(_), do: %{}
+end
diff --git a/lib/console/ai/tools/workbench/subagent.ex b/lib/console/ai/tools/workbench/subagent.ex
index e641a42f7f..cf854aa894 100644
--- a/lib/console/ai/tools/workbench/subagent.ex
+++ b/lib/console/ai/tools/workbench/subagent.ex
@@ -11,7 +11,8 @@ defmodule Console.AI.Tools.Workbench.Subagent do
history: 5,
search: 6,
verify: 7,
- monitoring: 8
+ monitoring: 8,
+ self_service: 9
embedded_schema do
field :subagents, {:array, Subagent}, virtual: true
diff --git a/lib/console/ai/tools/workbench/subagents.ex b/lib/console/ai/tools/workbench/subagents.ex
index fe529640e2..b36a5f4599 100644
--- a/lib/console/ai/tools/workbench/subagents.ex
+++ b/lib/console/ai/tools/workbench/subagents.ex
@@ -46,6 +46,7 @@ defmodule Console.AI.Tools.Workbench.Subagents do
defp subagent_description(_, :history, _, _), do: "Invoke a history subagent to search past workbench activities. Useful to remember what has been done so far, with regex support for finding past work."
defp subagent_description(_, :search, _, _), do: "Invoke a web search subagent to search the public web for information. Useful to find documentation, public pricing information, and anything else that's not specific to deployed infrastructure."
defp subagent_description(_, :verify, _, _), do: "Invoke a verification subagent to verify the job was successfully completed based on infrastructure and observability state."
+ defp subagent_description(_, :self_service, _, _), do: "Invoke a self-service subagent to discover Plural catalogs and PR automations, then invoke a clear GitOps provisioning pathway. Prefer this for repeatable golden-path provisioning; punt undefined or custom code work to the coding subagent."
defp subagent_description(_, _, _, _), do: "Unknown subagent"
defp infra_description(%{vulnerabilities: vulns, pod_logs: logs}) when vulns or logs do
diff --git a/lib/console/ai/workbench/engine.ex b/lib/console/ai/workbench/engine.ex
index 58c8d9cb92..30f0896677 100644
--- a/lib/console/ai/workbench/engine.ex
+++ b/lib/console/ai/workbench/engine.ex
@@ -292,7 +292,7 @@ defmodule Console.AI.Workbench.Engine do
defp action_call_id(%{id: %Console.AI.Tool{id: id}}), do: id
defp action_call_id(_), do: nil
- @supported_subagents ~w(infrastructure integration coding observability monitoring memory skill history search verify)a
+ @supported_subagents ~w(infrastructure integration coding observability monitoring memory skill history search verify self_service)a
defp spawn_activity(action, %__MODULE__{job: job} = engine) do
Tracking.with_activity(action, job, fn ->
@@ -453,6 +453,7 @@ defmodule Console.AI.Workbench.Engine do
defp subagent_module(:skill), do: SA.Skill
defp subagent_module(:search), do: SA.Search
defp subagent_module(:verify), do: SA.Verify
+ defp subagent_module(:self_service), do: SA.SelfService
defp tool_attrs(%{id: %Console.AI.Tool{id: id, name: name, arguments: arguments}}) when is_binary(id) and is_binary(name),
do: %{call_id: id, name: name, arguments: arguments}
diff --git a/lib/console/ai/workbench/environment.ex b/lib/console/ai/workbench/environment.ex
index 2be05366a2..30d7fa7f6c 100644
--- a/lib/console/ai/workbench/environment.ex
+++ b/lib/console/ai/workbench/environment.ex
@@ -136,6 +136,7 @@ defmodule Console.AI.Workbench.Environment do
|> Enum.concat(type_subagents(job))
|> Enum.concat(coding_agents(bench))
|> Enum.concat(infra_agents(bench))
+ |> Enum.concat(self_service_agents(bench))
|> Enum.filter(&allow_subagent?(job, &1))
end
@@ -210,6 +211,9 @@ defmodule Console.AI.Workbench.Environment do
end
defp infra_agents(_), do: []
+ defp self_service_agents(%Workbench{configuration: %{self_service: true}}), do: [:self_service]
+ defp self_service_agents(_), do: []
+
defp type_subagents(%WorkbenchJob{type: :skill}), do: [:history, :skill]
defp type_subagents(_), do: [:monitoring]
diff --git a/lib/console/ai/workbench/subagents/self_service.ex b/lib/console/ai/workbench/subagents/self_service.ex
new file mode 100644
index 0000000000..5d3b466e2c
--- /dev/null
+++ b/lib/console/ai/workbench/subagents/self_service.ex
@@ -0,0 +1,67 @@
+defmodule Console.AI.Workbench.Subagents.SelfService do
+ use Console.AI.Workbench.Subagents.Base
+ alias Console.Schema.{WorkbenchJob, WorkbenchJobActivity}
+ alias Console.AI.Tools.Agent.{Catalogs, PrAutomations}
+ alias Console.AI.Tools.Workbench.{
+ History,
+ Result,
+ Scratchpad,
+ Coding.PullRequests
+ }
+ alias Console.AI.Tools.Workbench.SelfService.{
+ CatalogSearch,
+ GetPrAutomation,
+ InvokePrAutomation
+ }
+ alias Console.AI.Workbench.Environment
+ import Console.AI.Workbench.Environment, only: [engine_opts: 1]
+
+ require EEx
+
+ def run(%WorkbenchJobActivity{prompt: prompt} = activity, %WorkbenchJob{} = job, %Environment{} = environment) do
+ tools(environment)
+ |> MemoryEngine.new(20,
+ engine_opts(environment) ++ [
+ system_prompt: String.trim(system_prompt(prompt: WorkbenchJob.objective(job))),
+ acc: %{},
+ callback: &callback(activity, environment, &1),
+ continue_msg: cont_msg()
+ ]
+ )
+ |> MemoryEngine.reduce([{:user, prompt}], &reducer/2)
+ |> case do
+ {:ok, attrs} -> attrs
+ {:error, error} -> %{status: :failed, result: %{error: "error running self-service subagent: #{inspect(error)}"}}
+ end
+ end
+
+ defp reducer(messages, _) do
+ case Enum.find(messages, &match?(%Result{}, &1)) do
+ %Result{output: output} -> {:halt, %{
+ status: :successful,
+ result: %{output: output}
+ }}
+ _ -> last_message(messages, & {:cont, %{status: :failed, result: %{error: &1}}})
+ end
+ end
+
+ defp tools(%Environment{skills: skills, job: job, activities: activities}) do
+ skills = Environment.subagent_skills(skills, :self_service)
+
+ [
+ Catalogs,
+ PrAutomations,
+ CatalogSearch,
+ GetPrAutomation,
+ %InvokePrAutomation{job: job},
+ %PullRequests{job: job}
+ ]
+ |> Enum.concat(skill_knowledge_tools(job, skills) ++ [
+ Scratchpad,
+ %History{job: job, activities: activities},
+ Result
+ ])
+ end
+
+ EEx.function_from_file(:defp, :system_prompt, Console.priv_filename(["prompts", "workbench", "self_service.md.eex"]), [:assigns])
+end
diff --git a/lib/console/graphql/deployments/workbench.ex b/lib/console/graphql/deployments/workbench.ex
index f6a175acde..e6ec55d2c0 100644
--- a/lib/console/graphql/deployments/workbench.ex
+++ b/lib/console/graphql/deployments/workbench.ex
@@ -89,6 +89,7 @@ defmodule Console.GraphQl.Deployments.Workbench do
end
input_object :workbench_configuration_attributes do
+ field :self_service, :boolean, description: "enable the self-service subagent for catalog and PR automation workflows"
field :infrastructure, :workbench_infrastructure_attributes, description: "infrastructure capabilities (services, stacks, kubernetes)"
field :coding, :workbench_coding_attributes, description: "coding capabilities (mode, repositories, babysitting)"
field :observability, :workbench_observability_attributes, description: "observability capabilities (logs, metrics)"
@@ -975,6 +976,7 @@ defmodule Console.GraphQl.Deployments.Workbench do
end
object :workbench_configuration do
+ field :self_service, :boolean, description: "self-service subagent capability enabled"
field :infrastructure, :workbench_infrastructure, description: "infrastructure capabilities"
field :coding, :workbench_coding, description: "coding capabilities"
field :observability, :workbench_observability, description: "observability capabilities"
diff --git a/lib/console/schema/workbench.ex b/lib/console/schema/workbench.ex
index 4e25f17002..e229db1175 100644
--- a/lib/console/schema/workbench.ex
+++ b/lib/console/schema/workbench.ex
@@ -108,6 +108,8 @@ defmodule Console.Schema.Workbench do
field :memory, Type
embeds_one :configuration, Configuration, on_replace: :update do
+ field :self_service, :boolean, default: false
+
embeds_one :infrastructure, Infrastructure, on_replace: :update do
field :services, :boolean
field :stacks, :boolean
@@ -253,7 +255,7 @@ defmodule Console.Schema.Workbench do
def configuration_changeset(model, attrs \\ %{}) do
model
- |> cast(attrs, [])
+ |> cast(attrs, [:self_service])
|> cast_embed(:infrastructure, with: &infrastructure_changeset/2)
|> cast_embed(:coding, with: &coding_changeset/2)
|> cast_embed(:observability, with: &observability_changeset/2)
diff --git a/lib/console/schema/workbench_job_activity.ex b/lib/console/schema/workbench_job_activity.ex
index e574b6430f..5f649130a6 100644
--- a/lib/console/schema/workbench_job_activity.ex
+++ b/lib/console/schema/workbench_job_activity.ex
@@ -22,7 +22,8 @@ defmodule Console.Schema.WorkbenchJobActivity do
kubernetes: 15,
verify: 16,
exec: 17,
- monitoring: 18
+ monitoring: 18,
+ self_service: 19
defguard is_action(type) when type in [:function, :kubernetes, :exec, :monitoring]
diff --git a/lib/console/schema/workbench_skill.ex b/lib/console/schema/workbench_skill.ex
index 11587d46d5..c1b4aff564 100644
--- a/lib/console/schema/workbench_skill.ex
+++ b/lib/console/schema/workbench_skill.ex
@@ -12,7 +12,8 @@ defmodule Console.Schema.WorkbenchSkill do
skill: 6,
history: 7,
search: 8,
- monitoring: 9
+ monitoring: 9,
+ self_service: 10
schema "workbench_skills" do
field :name, :string
diff --git a/priv/prompts/workbench/job.md.eex b/priv/prompts/workbench/job.md.eex
index 45b2a14c63..c918b5f885 100644
--- a/priv/prompts/workbench/job.md.eex
+++ b/priv/prompts/workbench/job.md.eex
@@ -15,6 +15,7 @@ the task. You'll be given the following:
7. the ability to record notes and modify your current plan and working theory of how to accomplish the task along the way to memorize progress.
8. a search agent to search the web for information. Useful to find information that is not already in the workbench environment.
9. a verification agent which will be present when a change relevant to this job has been fully applied. This is not always present, and will be included when verification is possible.
+ 10. a self-service agent for clear, repeatable GitOps provisioning through Plural catalogs and PR automations. Prefer this for golden-path provisioning; undefined or custom code work should use the coding agent instead.
Basic guardrails for using these subagents:
@@ -22,6 +23,7 @@ Basic guardrails for using these subagents:
* All log, timeseries and trace data should be queried using the observability agent.
* Delegate persistent dashboard and monitor creation, updates, imports, and deletion to the monitoring agent. It can query observability data itself to validate the configuration it manages.
* When you're ready to inspect code, leverage the coding agent to either analyze or modify code, generating a pull request in write mode.
+* When the task is clear, repeatable GitOps provisioning and a catalog PR automation likely covers it, prefer the self-service agent. If the pathway is undefined or needs custom code changes, use the coding agent instead.
<%= if @review do %>
* Pull request review is in scope for this job. When the task is to review a PR, launch the coding subagent and instruct it to use review mode with the PR URL and the PR's head branch (the branch containing the changes). Do not use analyze or write mode to inspect an existing PR.
* The coding agent owns the entire review, including publishing its summary and inline findings. Do not delegate any part of pull request review or review publication to the integration subagent or SCM integration tools.
@@ -155,6 +157,8 @@ Of all the subagents, coding has the highest cost to run, since it spawns a dedi
to gather the information needed to then prompt it, which should be reserved for codebase analysis<%= if @review do %>, pull request review,<% end %> and generation of PRs. Once you have a cleanly crafted prompt to delegate,
then do so if the user requires it to complete their task.
+If a clear Plural catalog/PR automation golden path exists for the request, prefer the `self_service` subagent before coding. Self-service should usually only be used for clear provisioning pathways and usually only for GitOps tasks; an undefined task needs the coding agent.
+
Two agents can give useful information about the codebase defining the system:
1. `coding` is effective for introspecting application code, and modifying it<%= if @review do %>, and for reviewing existing pull requests<% end %>. It can also be used to modify GitOps/IaC, but you likely need additional information
diff --git a/priv/prompts/workbench/self_service.md.eex b/priv/prompts/workbench/self_service.md.eex
new file mode 100644
index 0000000000..6be6e34ffb
--- /dev/null
+++ b/priv/prompts/workbench/self_service.md.eex
@@ -0,0 +1,37 @@
+You're a senior engineer focusing on clear, repeatable GitOps provisioning through Plural catalogs and PR automations.
+
+Use this subagent only for well-defined provisioning pathways that map to an existing PR automation. Prefer golden paths over one-off code edits. If the task is undefined, exploratory, or requires custom application/infrastructure code changes that no automation covers, finish with `subagent_result` explaining that the coding agent is the better next step.
+
+# Workflow
+
+1. List catalogs available to the current user.
+2. Search or list PR automations within the most relevant catalogs.
+3. Inspect a candidate automation (`workbench_get_pr_automation`) to understand documentation, required configuration fields, branch defaults, and confirmation requirements.
+4. Infer configuration values when you can. Leave uncertain values blank rather than inventing them.
+5. Invoke at most one clearly relevant automation with a descriptive source branch.
+6. Summarize the created pull request or explain why no automation was appropriate.
+
+# Guardrails
+
+* Self-service is usually only valid for clear GitOps/provisioning tasks.
+* Do not force-fit an automation. If none are relevant, call `subagent_result` and recommend the coding agent.
+* Prefer a single invocation. Do not repeatedly invoke the same automation.
+* Do not invent configuration. Prefer inspecting the automation first.
+* Generated PRs are automatically associated with this workbench job; include the PR URL and title in your result.
+* You can list pull requests already created for this job when useful for continuity.
+
+# Tone of Voice Guidance
+
+You are producing output for a human user, and should expect them to want to read as little as possible and mostly be scanning. You should be:
+
+* as concise as possible
+* still provide critical information needed to convey the result
+* use supporting markdown formatting where needed to improve scannability
+
+# Ideal Output
+
+Summarize what catalog/automation path you chose, what PR was created (if any), and any gaps or reasons you punted. Always call `subagent_result` exactly once when done.
+
+The overarching task is as follows:
+
+<%= @prompt %>
diff --git a/priv/tools/workbench/self_service/catalog_search.json b/priv/tools/workbench/self_service/catalog_search.json
new file mode 100644
index 0000000000..2be35245be
--- /dev/null
+++ b/priv/tools/workbench/self_service/catalog_search.json
@@ -0,0 +1,10 @@
+{
+ "type": "object",
+ "properties": {
+ "query": {
+ "type": "string",
+ "description": "Semantic or name search query for catalogs and PR automations"
+ }
+ },
+ "required": ["query"]
+}
diff --git a/priv/tools/workbench/self_service/get_pr_automation.json b/priv/tools/workbench/self_service/get_pr_automation.json
new file mode 100644
index 0000000000..1bb06fabe1
--- /dev/null
+++ b/priv/tools/workbench/self_service/get_pr_automation.json
@@ -0,0 +1,14 @@
+{
+ "type": "object",
+ "properties": {
+ "pr_automation_id": {
+ "type": "string",
+ "description": "The id of the PR automation to fetch. Prefer this when you already have an id from list or search results."
+ },
+ "name": {
+ "type": "string",
+ "description": "The name of the PR automation to fetch when you do not yet have its id."
+ }
+ },
+ "required": []
+}
diff --git a/priv/tools/workbench/self_service/invoke_pr_automation.json b/priv/tools/workbench/self_service/invoke_pr_automation.json
new file mode 100644
index 0000000000..e6773f12fb
--- /dev/null
+++ b/priv/tools/workbench/self_service/invoke_pr_automation.json
@@ -0,0 +1,22 @@
+{
+ "type": "object",
+ "properties": {
+ "pr_automation_id": {
+ "type": "string",
+ "description": "The id of the PR automation to invoke."
+ },
+ "context": {
+ "type": "string",
+ "description": "A JSON-encoded string-valued map filling the PR automation configuration fields. Keys are configuration field names and values are the chosen inputs."
+ },
+ "branch": {
+ "type": "string",
+ "description": "The source branch name for the generated pull request. Use a concise, descriptive name and avoid existing branches."
+ },
+ "identifier": {
+ "type": "string",
+ "description": "Optional repository identifier override (for example owner/repo). Leave unset to use the automation default."
+ }
+ },
+ "required": ["pr_automation_id", "branch"]
+}
diff --git a/schema/schema.graphql b/schema/schema.graphql
index 1607d6beb5..5a756fe870 100644
--- a/schema/schema.graphql
+++ b/schema/schema.graphql
@@ -3029,6 +3029,7 @@ enum WorkbenchJobActivityType {
VERIFY
EXEC
MONITORING
+ SELF_SERVICE
}
enum WorkbenchCanvasBlockType {
@@ -3051,6 +3052,7 @@ enum WorkbenchSkillSubagent {
HISTORY
SEARCH
MONITORING
+ SELF_SERVICE
}
enum WorkbenchChatbotMessageBehavior {
@@ -3205,6 +3207,9 @@ input WorkbenchAttributes {
}
input WorkbenchConfigurationAttributes {
+ "enable the self-service subagent for catalog and PR automation workflows"
+ selfService: Boolean
+
"infrastructure capabilities (services, stacks, kubernetes)"
infrastructure: WorkbenchInfrastructureAttributes
@@ -4728,6 +4733,9 @@ type WorkbenchJobResultTodo {
}
type WorkbenchConfiguration {
+ "self-service subagent capability enabled"
+ selfService: Boolean
+
"infrastructure capabilities"
infrastructure: WorkbenchInfrastructure
diff --git a/test/console/ai/tools/workbench/self_service/catalog_search_test.exs b/test/console/ai/tools/workbench/self_service/catalog_search_test.exs
new file mode 100644
index 0000000000..fe2414682f
--- /dev/null
+++ b/test/console/ai/tools/workbench/self_service/catalog_search_test.exs
@@ -0,0 +1,35 @@
+defmodule Console.AI.Tools.Workbench.SelfService.CatalogSearchTest do
+ use Console.DataCase, async: true
+ alias Console.AI.Tools.Workbench.SelfService.CatalogSearch
+
+ describe "implement/1" do
+ test "falls back to name search when vector store is disabled" do
+ user = insert(:user)
+ catalog = insert(:catalog, name: "databases", read_bindings: [%{user_id: user.id}])
+ pra = insert(:pr_automation, name: "postgres-cluster", catalog: catalog, documentation: "Provision postgres")
+ insert(:pr_automation, name: "unrelated", documentation: "other")
+
+ Console.AI.Tool.context(%{user: user})
+
+ {:ok, result} = CatalogSearch.implement(%CatalogSearch{query: "postgres"})
+ {:ok, decoded} = Jason.decode(result)
+
+ assert Enum.any?(decoded, fn
+ %{"pr_automation" => %{"id" => id}} -> id == pra.id
+ _ -> false
+ end)
+ end
+
+ test "hides catalogs the user cannot read" do
+ user = insert(:user)
+ insert(:catalog, name: "secret-catalog")
+
+ Console.AI.Tool.context(%{user: user})
+
+ {:ok, result} = CatalogSearch.implement(%CatalogSearch{query: "secret"})
+ {:ok, decoded} = Jason.decode(result)
+
+ assert decoded == []
+ end
+ end
+end
diff --git a/test/console/ai/tools/workbench/self_service/get_pr_automation_test.exs b/test/console/ai/tools/workbench/self_service/get_pr_automation_test.exs
new file mode 100644
index 0000000000..f762e894cd
--- /dev/null
+++ b/test/console/ai/tools/workbench/self_service/get_pr_automation_test.exs
@@ -0,0 +1,52 @@
+defmodule Console.AI.Tools.Workbench.SelfService.GetPrAutomationTest do
+ use Console.DataCase, async: true
+ alias Console.AI.Tools.Workbench.SelfService.GetPrAutomation
+
+ describe "implement/1" do
+ test "returns automation details for catalog readers" do
+ user = insert(:user)
+ catalog = insert(:catalog, read_bindings: [%{user_id: user.id}])
+ pra = insert(:pr_automation,
+ catalog: catalog,
+ documentation: "Creates a managed postgres",
+ title: "Add postgres",
+ branch: "plrl/postgres"
+ )
+
+ Console.AI.Tool.context(%{user: user})
+
+ {:ok, result} = GetPrAutomation.implement(%GetPrAutomation{pr_automation_id: pra.id})
+ {:ok, decoded} = Jason.decode(result)
+
+ assert decoded["id"] == pra.id
+ assert decoded["documentation"] == "Creates a managed postgres"
+ assert decoded["title"] == "Add postgres"
+ assert decoded["branch"] == "plrl/postgres"
+ assert decoded["catalog"]["id"] == catalog.id
+ end
+
+ test "supports lookup by name" do
+ user = insert(:user)
+ catalog = insert(:catalog, read_bindings: [%{user_id: user.id}])
+ pra = insert(:pr_automation, name: "named-pra", catalog: catalog)
+
+ Console.AI.Tool.context(%{user: user})
+
+ {:ok, result} = GetPrAutomation.implement(%GetPrAutomation{name: "named-pra"})
+ {:ok, decoded} = Jason.decode(result)
+
+ assert decoded["id"] == pra.id
+ end
+
+ test "denies users without catalog access" do
+ user = insert(:user)
+ catalog = insert(:catalog)
+ pra = insert(:pr_automation, catalog: catalog)
+
+ Console.AI.Tool.context(%{user: user})
+
+ {:ok, result} = GetPrAutomation.implement(%GetPrAutomation{pr_automation_id: pra.id})
+ assert result =~ "do not have access"
+ end
+ end
+end
diff --git a/test/console/ai/tools/workbench/self_service/invoke_pr_automation_test.exs b/test/console/ai/tools/workbench/self_service/invoke_pr_automation_test.exs
new file mode 100644
index 0000000000..70831659e3
--- /dev/null
+++ b/test/console/ai/tools/workbench/self_service/invoke_pr_automation_test.exs
@@ -0,0 +1,54 @@
+defmodule Console.AI.Tools.Workbench.SelfService.InvokePrAutomationTest do
+ use Console.DataCase, async: true
+ use Mimic
+ alias Console.AI.Tools.Workbench.SelfService.InvokePrAutomation
+ alias Console.Deployments.Pr.Dispatcher
+
+ describe "implement/1" do
+ test "creates a pull request associated with the workbench job" do
+ user = insert(:user)
+ job = insert(:workbench_job, user: user)
+ pra = insert(:pr_automation, create_bindings: [%{user_id: user.id}])
+
+ expect(Dispatcher, :create, fn _, "plrl/self-service", %{"cluster" => "dev"} ->
+ {:ok, %{url: "https://github.com/pluralsh/console/pull/1", title: "Provision cluster"}}
+ end)
+
+ Console.AI.Tool.context(%{user: user, job: job})
+
+ {:ok, result} =
+ InvokePrAutomation.implement(%InvokePrAutomation{
+ pr_automation_id: pra.id,
+ branch: "plrl/self-service",
+ context: Jason.encode!(%{"cluster" => "dev"}),
+ job: job
+ })
+
+ {:ok, decoded} = Jason.decode(result)
+
+ assert decoded["url"] == "https://github.com/pluralsh/console/pull/1"
+ assert decoded["title"] == "Provision cluster"
+ assert decoded["workbench_job_id"] == job.id
+ assert decoded["workbench_id"] == job.workbench_id
+ assert decoded["status"] == "open"
+ end
+
+ test "returns permission failures without creating a pull request" do
+ user = insert(:user)
+ job = insert(:workbench_job, user: user)
+ pra = insert(:pr_automation)
+
+ Console.AI.Tool.context(%{user: user, job: job})
+
+ {:ok, result} =
+ InvokePrAutomation.implement(%InvokePrAutomation{
+ pr_automation_id: pra.id,
+ branch: "plrl/self-service",
+ context: "{}",
+ job: job
+ })
+
+ assert result =~ "failed to create pull request"
+ end
+ end
+end
diff --git a/test/console/ai/tools/workbench/subagents_test.exs b/test/console/ai/tools/workbench/subagents_test.exs
index 88233d4802..4cfe100869 100644
--- a/test/console/ai/tools/workbench/subagents_test.exs
+++ b/test/console/ai/tools/workbench/subagents_test.exs
@@ -80,6 +80,34 @@ defmodule Console.AI.Tools.Workbench.SubagentsTest do
assert description =~ "metrics, logs"
end
+ test "describes self_service as catalog and PR automation workflows" do
+ {:ok, encoded} =
+ Subagents.implement(%Subagents{
+ bench: %Workbench{},
+ job: %WorkbenchJob{},
+ subagents: [:self_service],
+ categories: []
+ })
+
+ assert [%{"name" => "self_service", "description" => description}] =
+ Jason.decode!(encoded)
+
+ assert description =~ "catalog"
+ assert description =~ "PR automation"
+ assert description =~ "coding"
+ end
+
+ test "accepts the self_service subagent" do
+ assert {:ok, %Subagent{subagent: :self_service}} =
+ Tool.validate(
+ %Subagent{subagents: [:self_service]},
+ %{
+ "subagent" => "self_service",
+ "prompt" => "Provision a postgres cluster via catalog automation"
+ }
+ )
+ end
+
test "mentions review mode on the coding subagent only when enabled" do
{:ok, encoded} =
Subagents.implement(%Subagents{
diff --git a/test/console/ai/workbench/environment_test.exs b/test/console/ai/workbench/environment_test.exs
index 3f19313213..12f4fe1f60 100644
--- a/test/console/ai/workbench/environment_test.exs
+++ b/test/console/ai/workbench/environment_test.exs
@@ -61,6 +61,20 @@ defmodule Console.AI.Workbench.EnvironmentTest do
)
end
+ test "includes self_service when configuration.self_service is enabled" do
+ workbench = insert(:workbench, configuration: %{self_service: true})
+ job = insert(:workbench_job, workbench: workbench) |> Repo.preload(workbench: :tools)
+
+ assert :self_service in Environment.subagents(job)
+ end
+
+ test "excludes self_service when configuration.self_service is absent" do
+ workbench = insert(:workbench, configuration: %{infrastructure: %{services: true}})
+ job = insert(:workbench_job, workbench: workbench) |> Repo.preload(workbench: :tools)
+
+ refute :self_service in Environment.subagents(job)
+ end
+
test "exposes docker/oci tools on both the infrastructure and integration subagents" do
workbench = insert(:workbench)
docker_tool =
diff --git a/test/console/ai/workbench/subagents/self_service_test.exs b/test/console/ai/workbench/subagents/self_service_test.exs
new file mode 100644
index 0000000000..958ce90810
--- /dev/null
+++ b/test/console/ai/workbench/subagents/self_service_test.exs
@@ -0,0 +1,72 @@
+defmodule Console.AI.Workbench.Subagents.SelfServiceTest do
+ use Console.DataCase, async: false
+ use Mimic
+ alias Console.AI.Tool
+ alias Console.AI.Workbench.{Engine, Environment, Subagents.SelfService}
+ alias Console.AI.Tools.Workbench.SelfService.InvokePrAutomation
+ alias Console.Deployments.Pr.Dispatcher
+
+ setup :set_mimic_global
+
+ describe "run/3" do
+ test "invokes a PR automation and returns subagent_result output" do
+ deployment_settings(ai: %{
+ enabled: true,
+ provider: :openai,
+ openai: %{access_token: "key"}
+ })
+
+ user = insert(:user)
+ workbench = insert(:workbench, configuration: %{self_service: true})
+ job = insert(:workbench_job, workbench: workbench, user: user, prompt: "Provision postgres")
+ activity = insert(:workbench_job_activity, workbench_job: job, type: :self_service, prompt: "Find and invoke the postgres automation")
+ catalog = insert(:catalog, name: "databases", read_bindings: [%{user_id: user.id}])
+ pra = insert(:pr_automation,
+ name: "postgres",
+ catalog: catalog,
+ create_bindings: [%{user_id: user.id}],
+ documentation: "Provision postgres"
+ )
+
+ expect(Dispatcher, :create, fn _, "plrl/postgres", _ ->
+ {:ok, %{url: "https://github.com/pluralsh/console/pull/22", title: "Add postgres"}}
+ end)
+
+ expect_reqllm_completion(fn _, _ ->
+ {:ok, "listing catalogs", [
+ %Tool{name: "__plrl__catalogs", arguments: %{}, id: "1"}
+ ]}
+ end)
+
+ expect_reqllm_completion(fn msgs, _ ->
+ assert Enum.any?(msgs, &match?({:tool, _, %{name: "__plrl__catalogs"}}, &1))
+
+ {:ok, "invoking", [
+ %Tool{
+ name: InvokePrAutomation.name(%InvokePrAutomation{}),
+ arguments: %{
+ "pr_automation_id" => pra.id,
+ "branch" => "plrl/postgres",
+ "context" => "{}"
+ },
+ id: "2"
+ }
+ ]}
+ end)
+
+ expect_reqllm_completion(fn msgs, _ ->
+ assert Enum.any?(msgs, &match?({:tool, _, %{name: "workbench_invoke_pr_automation"}}, &1))
+
+ {:ok, "done", [
+ %Tool{name: "subagent_result", arguments: %{"output" => "Created postgres PR"}, id: "3"}
+ ]}
+ end)
+
+ {:ok, _engine} = Engine.new(job)
+ result = SelfService.run(activity, job, Environment.new(job, [], []))
+
+ assert result[:status] == :successful
+ assert result[:result][:output] == "Created postgres PR"
+ end
+ end
+end
diff --git a/test/console/graphql/mutations/deployments/workbench_mutations_test.exs b/test/console/graphql/mutations/deployments/workbench_mutations_test.exs
index f8de82ebfa..04529736a5 100644
--- a/test/console/graphql/mutations/deployments/workbench_mutations_test.exs
+++ b/test/console/graphql/mutations/deployments/workbench_mutations_test.exs
@@ -43,6 +43,7 @@ defmodule Console.GraphQl.Deployments.WorkbenchMutationsTest do
"name" => "configured-workbench",
"projectId" => project.id,
"configuration" => %{
+ "selfService" => true,
"infrastructure" => %{"services" => true, "stacks" => true, "kubernetes" => false},
"coding" => %{"mode" => "ANALYZE", "repositories" => ["repo1", "repo2"]}
}
@@ -54,6 +55,7 @@ defmodule Console.GraphQl.Deployments.WorkbenchMutationsTest do
id
name
configuration {
+ selfService
infrastructure { services stacks kubernetes }
coding { mode repositories }
}
@@ -62,6 +64,7 @@ defmodule Console.GraphQl.Deployments.WorkbenchMutationsTest do
""", %{"attributes" => attrs}, %{current_user: admin_user()})
assert workbench["name"] == "configured-workbench"
+ assert workbench["configuration"]["selfService"] == true
assert workbench["configuration"]["infrastructure"]["services"] == true
assert workbench["configuration"]["infrastructure"]["stacks"] == true
assert workbench["configuration"]["infrastructure"]["kubernetes"] == false
@@ -182,6 +185,7 @@ defmodule Console.GraphQl.Deployments.WorkbenchMutationsTest do
attrs = %{
"name" => workbench.name,
"configuration" => %{
+ "selfService" => true,
"infrastructure" => %{"services" => false, "stacks" => true, "kubernetes" => true},
"coding" => %{"mode" => "WRITE", "repositories" => ["single-repo"]}
}
@@ -192,6 +196,7 @@ defmodule Console.GraphQl.Deployments.WorkbenchMutationsTest do
updateWorkbench(id: $id, attributes: $attributes) {
id
configuration {
+ selfService
infrastructure { services stacks kubernetes }
coding { mode repositories }
}
@@ -200,6 +205,7 @@ defmodule Console.GraphQl.Deployments.WorkbenchMutationsTest do
""", %{"id" => workbench.id, "attributes" => attrs}, %{current_user: admin_user()})
assert updated["id"] == workbench.id
+ assert updated["configuration"]["selfService"] == true
assert updated["configuration"]["infrastructure"]["services"] == false
assert updated["configuration"]["infrastructure"]["stacks"] == true
assert updated["configuration"]["infrastructure"]["kubernetes"] == true