@cat-factory/app 0.309.0 → 0.310.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -2
- package/app/components/assistant/AssistantModal.vue +5 -4
- package/app/components/auth/BackendMisconfiguredScreen.vue +4 -3
- package/app/components/auth/LoginScreen.vue +40 -26
- package/app/components/auth/ResetPasswordScreen.vue +9 -4
- package/app/components/auth/UserMenu.vue +4 -3
- package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +34 -23
- package/app/components/binaryOutput/StoredAssetView.vue +8 -6
- package/app/components/board/AddTaskModal.vue +16 -15
- package/app/components/board/AgentFailureCard.vue +12 -9
- package/app/components/board/AgentFailureHistory.vue +18 -9
- package/app/components/board/CreateInitiativeModal.vue +5 -4
- package/app/components/board/FailureDetail.vue +22 -12
- package/app/components/board/ReviewFrictionDialog.vue +4 -3
- package/app/components/board/nodes/BlockNode.vue +17 -15
- package/app/components/board/nodes/DecisionBadge.vue +4 -3
- package/app/components/board/nodes/FrameSwimlanes.vue +4 -3
- package/app/components/board/nodes/TaskCard.vue +12 -7
- package/app/components/board/nodes/TaskPipelineMini.vue +9 -7
- package/app/components/bootstrap/AdoptionReviewModal.vue +30 -21
- package/app/components/bootstrap/BootstrapModal.vue +3 -3
- package/app/components/brainstorm/BrainstormWindow.vue +5 -3
- package/app/components/bugFishing/BugFishingWindow.vue +49 -27
- package/app/components/clarity/ClarityReviewWindow.vue +5 -3
- package/app/components/common/CopyButton.vue +12 -11
- package/app/components/common/IconButton.vue +34 -9
- package/app/components/context/ContextAttachmentFields.vue +23 -12
- package/app/components/documents/ContextDocumentPicker.vue +12 -9
- package/app/components/documents/DocumentImportModal.vue +4 -3
- package/app/components/documents/DocumentOriginLink.vue +12 -9
- package/app/components/documents/DocumentSyncState.vue +3 -3
- package/app/components/documents/RepoContextDocPicker.vue +4 -3
- package/app/components/environments/EnvironmentStatusPanel.vue +4 -3
- package/app/components/followUp/FollowUpWindow.vue +9 -6
- package/app/components/forkDecision/ForkDecisionWindow.vue +71 -80
- package/app/components/foundational/FoundationalServiceCatalogList.vue +3 -2
- package/app/components/foundational/FoundationalServiceRegistry.vue +7 -6
- package/app/components/foundational/FoundationalServiceSources.vue +7 -6
- package/app/components/fragments/FragmentLibraryManager.vue +5 -4
- package/app/components/fragments/FragmentSelector.vue +12 -9
- package/app/components/gates/GateFailingCheckList.vue +4 -3
- package/app/components/gates/GateResultView.vue +17 -12
- package/app/components/github/AddServiceFromRepoModal.vue +11 -7
- package/app/components/github/GitHubOnboarding.vue +7 -2
- package/app/components/github/GitHubPanel.vue +9 -6
- package/app/components/github/RepoTreeBrowser.vue +15 -12
- package/app/components/humanTest/HumanTestWindow.vue +13 -9
- package/app/components/initiative/InitiativePlanReview.vue +28 -18
- package/app/components/initiative/InitiativeTrackerWindow.vue +171 -124
- package/app/components/judge/JudgeResultView.vue +5 -3
- package/app/components/kaizen/KaizenPanel.vue +67 -53
- package/app/components/layout/AccountTeamSettings.vue +9 -9
- package/app/components/layout/AppearanceSwitcher.vue +4 -3
- package/app/components/layout/BoardSwitcher.vue +10 -8
- package/app/components/layout/BoardToolbar.vue +5 -4
- package/app/components/layout/CommandBar.vue +4 -3
- package/app/components/layout/DefaultTestEnvBanner.vue +4 -3
- package/app/components/layout/IntegrationsHub.vue +8 -6
- package/app/components/layout/LanguageSwitcher.vue +4 -3
- package/app/components/layout/ModelProvidersHub.vue +4 -3
- package/app/components/layout/NotificationsInbox.vue +40 -30
- package/app/components/layout/PersonalSetupModal.vue +4 -3
- package/app/components/layout/RolePrompt.vue +4 -3
- package/app/components/layout/SideBar.vue +4 -3
- package/app/components/layout/TranslationWarningBanner.vue +4 -3
- package/app/components/layout/UiModeSwitcher.vue +8 -6
- package/app/components/layout/UiRoleSwitcher.vue +8 -6
- package/app/components/layout/WorkspaceMembersSettings.vue +2 -2
- package/app/components/media/ArtifactLightbox.vue +69 -39
- package/app/components/media/ImageCompare.vue +69 -74
- package/app/components/observability/OutcomeFilterChips.vue +5 -4
- package/app/components/observability/RunFailureSummary.vue +8 -6
- package/app/components/observability/StepModelActivity.vue +5 -3
- package/app/components/observability/ToolCallList.vue +4 -2
- package/app/components/outcome/OutcomeSummaryWindow.vue +5 -4
- package/app/components/palettes/AgentPalette.vue +18 -14
- package/app/components/panels/AgentStepDetail.vue +30 -19
- package/app/components/panels/ObservabilityPanel.vue +149 -114
- package/app/components/panels/OperatorDashboardPanel.vue +99 -91
- package/app/components/panels/ReportsPanel.vue +64 -61
- package/app/components/panels/ResultWindowShell.vue +148 -134
- package/app/components/panels/StepContainerStatus.vue +9 -9
- package/app/components/panels/StepDelegatedStatus.vue +11 -9
- package/app/components/panels/StepRestartControl.vue +3 -2
- package/app/components/panels/inspector/EpicChildren.vue +4 -3
- package/app/components/panels/inspector/FrontendConfig.vue +3 -2
- package/app/components/panels/inspector/InspectorSection.vue +22 -17
- package/app/components/panels/inspector/ServiceConnections.vue +3 -2
- package/app/components/panels/inspector/ServiceTestConfig.vue +5 -4
- package/app/components/panels/inspector/TaskExecution.vue +5 -4
- package/app/components/panels/inspector/TaskRunSettings.vue +10 -6
- package/app/components/pipeline/EstimateThresholdFields.vue +13 -10
- package/app/components/pipeline/GateConfigFields.vue +14 -18
- package/app/components/pipeline/PipelineBuilder.vue +90 -77
- package/app/components/pipeline/PipelinePicker.vue +8 -6
- package/app/components/pipeline/PipelineProgress.vue +26 -21
- package/app/components/prReview/PrReviewWindow.vue +46 -25
- package/app/components/providers/ApiKeysSection.vue +4 -3
- package/app/components/ralph/RalphLoopResultView.vue +4 -3
- package/app/components/requirements/RequirementsReviewWindow.vue +10 -6
- package/app/components/riskPolicy/RiskPolicyPicker.vue +8 -6
- package/app/components/sandbox/SandboxPanel.vue +73 -54
- package/app/components/settings/CloudflareHandlerSection.vue +33 -30
- package/app/components/settings/ConsensusGroupsSection.vue +40 -30
- package/app/components/settings/InfraHandlersConfigurator.vue +16 -13
- package/app/components/settings/InfrastructureBackendPicker.vue +17 -17
- package/app/components/settings/IssueTrackerPanel.vue +21 -6
- package/app/components/settings/LocalModelEndpointsPanel.vue +3 -2
- package/app/components/settings/ModelConfigurationPanel.vue +9 -8
- package/app/components/settings/OpenRouterCatalogPanel.vue +4 -3
- package/app/components/settings/ProviderPreferenceEditor.vue +5 -6
- package/app/components/settings/RiskPolicyEditorRow.vue +3 -2
- package/app/components/settings/ServiceFragmentDefaultsPanel.vue +10 -8
- package/app/components/skills/ReviewSkillQueue.vue +4 -3
- package/app/components/skills/SkillLibraryManager.vue +7 -6
- package/app/components/slack/SlackPanel.vue +9 -5
- package/app/components/spec/ServiceSpecWindow.vue +4 -3
- package/app/components/tasks/ContextIssuePicker.vue +12 -9
- package/app/components/tasks/TaskContextIssues.vue +4 -3
- package/app/components/testing/TestReportWindow.vue +14 -8
- package/app/components/theme/ThemeImportModal.vue +2 -2
- package/app/components/visualConfirm/VisualConfirmationWindow.vue +62 -35
- package/i18n/locales/de.json +7 -3
- package/i18n/locales/en.json +7 -3
- package/i18n/locales/es.json +7 -3
- package/i18n/locales/fr.json +7 -3
- package/i18n/locales/he.json +7 -3
- package/i18n/locales/it.json +7 -3
- package/i18n/locales/ja.json +7 -3
- package/i18n/locales/pl.json +7 -3
- package/i18n/locales/tr.json +7 -3
- package/i18n/locales/uk.json +7 -3
- package/package.json +1 -1
|
@@ -386,9 +386,10 @@ async function mergePr() {
|
|
|
386
386
|
<div class="flex items-center gap-2">
|
|
387
387
|
<!-- Every agent is clickable: it opens the step-detail overlay (timing,
|
|
388
388
|
model, subtasks + the prose output when there is one). -->
|
|
389
|
-
<
|
|
390
|
-
|
|
391
|
-
|
|
389
|
+
<UButton
|
|
390
|
+
color="neutral"
|
|
391
|
+
variant="ghost"
|
|
392
|
+
class="flex min-w-0 cursor-pointer items-center gap-2 p-0 text-start transition hover:bg-transparent hover:text-highlighted"
|
|
392
393
|
data-testid="run-step-open"
|
|
393
394
|
:title="
|
|
394
395
|
stepHasOutput(s)
|
|
@@ -416,7 +417,7 @@ async function mergePr() {
|
|
|
416
417
|
:name="stepHasOutput(s) ? 'i-lucide-book-open-text' : 'i-lucide-info'"
|
|
417
418
|
class="h-3.5 w-3.5 shrink-0 text-dimmed"
|
|
418
419
|
/>
|
|
419
|
-
</
|
|
420
|
+
</UButton>
|
|
420
421
|
<span
|
|
421
422
|
v-if="s.subtasks && s.subtasks.total > 0"
|
|
422
423
|
class="ms-auto font-mono text-3xs tabular-nums text-toned"
|
|
@@ -434,18 +434,22 @@ const technicalLabel = computed(() => {
|
|
|
434
434
|
</i18n-t>
|
|
435
435
|
</p>
|
|
436
436
|
<div class="mt-1.5 flex flex-wrap gap-2">
|
|
437
|
-
<
|
|
438
|
-
|
|
437
|
+
<UButton
|
|
438
|
+
color="neutral"
|
|
439
|
+
variant="link"
|
|
440
|
+
class="p-0 text-xs font-medium text-app-warning-100 underline-offset-2 hover:underline"
|
|
439
441
|
@click="ui.openModelConfig()"
|
|
440
442
|
>
|
|
441
443
|
{{ t('inspector.runSettings.editPresets') }}
|
|
442
|
-
</
|
|
443
|
-
<
|
|
444
|
-
|
|
444
|
+
</UButton>
|
|
445
|
+
<UButton
|
|
446
|
+
color="neutral"
|
|
447
|
+
variant="link"
|
|
448
|
+
class="p-0 text-xs font-medium text-app-warning-100 underline-offset-2 hover:underline"
|
|
445
449
|
@click="ui.openVendorCredentials()"
|
|
446
450
|
>
|
|
447
451
|
{{ t('inspector.runSettings.configureVendors') }}
|
|
448
|
-
</
|
|
452
|
+
</UButton>
|
|
449
453
|
</div>
|
|
450
454
|
</div>
|
|
451
455
|
</div>
|
|
@@ -47,8 +47,10 @@ const fields = computed(() =>
|
|
|
47
47
|
})),
|
|
48
48
|
)
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
// The control hands back a number (or nothing when cleared); the shared parser still owns the
|
|
51
|
+
// clamping, so the value that leaves here is the same one the text input used to produce.
|
|
52
|
+
function commit(axis: EstimateAxis, raw: number | undefined) {
|
|
53
|
+
emit('update', axis, raw == null ? undefined : parseAxisThreshold(String(raw)))
|
|
52
54
|
}
|
|
53
55
|
</script>
|
|
54
56
|
|
|
@@ -59,15 +61,16 @@ function commit(axis: EstimateAxis, raw: string) {
|
|
|
59
61
|
</span>
|
|
60
62
|
<template v-for="f in fields" :key="f.axis">
|
|
61
63
|
<label class="text-muted" :title="f.hint">{{ f.label }}</label>
|
|
62
|
-
<
|
|
63
|
-
:value="f.value"
|
|
64
|
+
<UInputNumber
|
|
65
|
+
:model-value="f.value"
|
|
64
66
|
:title="f.hint"
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
step="
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
:min="0"
|
|
68
|
+
:max="1"
|
|
69
|
+
:step="0.1"
|
|
70
|
+
:step-snapping="false"
|
|
71
|
+
size="xs"
|
|
72
|
+
class="w-28"
|
|
73
|
+
@update:model-value="commit(f.axis, $event ?? undefined)"
|
|
71
74
|
/>
|
|
72
75
|
</template>
|
|
73
76
|
</div>
|
|
@@ -121,19 +121,15 @@ const gateFieldValues = computed<DescriptorFieldValues>({
|
|
|
121
121
|
>
|
|
122
122
|
<div class="flex flex-wrap items-center gap-2 text-3xs">
|
|
123
123
|
<span class="text-dimmed">{{ t('pipeline.gateConfig.approversLabel') }}</span>
|
|
124
|
-
<
|
|
124
|
+
<UCheckbox
|
|
125
125
|
v-for="role in APPROVER_ROLES"
|
|
126
126
|
:key="role"
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
@change="toggleRole(role, ($event.target as HTMLInputElement).checked)"
|
|
134
|
-
/>
|
|
135
|
-
{{ t(ROLE_LABEL_KEYS[role as 'admin' | 'member']) }}
|
|
136
|
-
</label>
|
|
127
|
+
size="xs"
|
|
128
|
+
:model-value="config.approvers?.roles?.includes(role) ?? false"
|
|
129
|
+
:label="t(ROLE_LABEL_KEYS[role as 'admin' | 'member'])"
|
|
130
|
+
:data-testid="`gate-approver-role-${role}`"
|
|
131
|
+
@update:model-value="toggleRole(role, $event === true)"
|
|
132
|
+
/>
|
|
137
133
|
</div>
|
|
138
134
|
|
|
139
135
|
<div class="flex flex-wrap items-center gap-2 text-3xs">
|
|
@@ -155,15 +151,15 @@ const gateFieldValues = computed<DescriptorFieldValues>({
|
|
|
155
151
|
<label class="text-dimmed" :title="t('pipeline.gateConfig.requiredApprovalsHint')">
|
|
156
152
|
{{ t('pipeline.gateConfig.requiredApprovalsLabel') }}
|
|
157
153
|
</label>
|
|
158
|
-
<
|
|
159
|
-
:value="requiredApprovals"
|
|
160
|
-
|
|
161
|
-
min="1"
|
|
154
|
+
<UInputNumber
|
|
155
|
+
:model-value="Number(requiredApprovals)"
|
|
156
|
+
:min="1"
|
|
162
157
|
:max="MAX_GATE_APPROVALS"
|
|
163
|
-
step="1"
|
|
164
|
-
|
|
158
|
+
:step="1"
|
|
159
|
+
size="xs"
|
|
160
|
+
class="w-24"
|
|
165
161
|
data-testid="gate-required-approvals"
|
|
166
|
-
@
|
|
162
|
+
@update:model-value="setRequiredApprovals(String($event ?? ''))"
|
|
167
163
|
/>
|
|
168
164
|
<span class="text-dimmed">{{ t('pipeline.gateConfig.requiredApprovalsHint') }}</span>
|
|
169
165
|
</div>
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
} from '~/utils/catalog'
|
|
30
30
|
import type { ConsensusStrategy } from '~/types/consensus'
|
|
31
31
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
32
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
32
33
|
|
|
33
34
|
type DraftUnit = { index: number; kind: AgentKind; companionIndex: number | null }
|
|
34
35
|
|
|
@@ -491,14 +492,24 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
491
492
|
class="gap-1"
|
|
492
493
|
>
|
|
493
494
|
{{ l }}
|
|
494
|
-
<
|
|
495
|
-
|
|
496
|
-
|
|
495
|
+
<IconButton
|
|
496
|
+
color="neutral"
|
|
497
|
+
variant="ghost"
|
|
498
|
+
size="xs"
|
|
499
|
+
icon="i-lucide-x"
|
|
500
|
+
:label="t('pipeline.builder.removeLabel', { label: l })"
|
|
501
|
+
:ui="{
|
|
502
|
+
base: 'p-0 hover:bg-transparent hover:text-app-error-400',
|
|
503
|
+
leadingIcon: 'h-3 w-3',
|
|
504
|
+
}"
|
|
505
|
+
@click="removeLabel(l)"
|
|
506
|
+
/>
|
|
497
507
|
</UBadge>
|
|
498
|
-
<
|
|
508
|
+
<UInput
|
|
499
509
|
v-model="newLabel"
|
|
510
|
+
size="xs"
|
|
511
|
+
class="w-20 focus-within:w-28"
|
|
500
512
|
:placeholder="t('pipeline.builder.labelPlaceholder')"
|
|
501
|
-
class="w-20 rounded-sm border border-muted bg-default px-1.5 py-0.5 text-2xs text-default focus:w-28"
|
|
502
513
|
@keydown.enter.prevent="addLabel"
|
|
503
514
|
@blur="addLabel"
|
|
504
515
|
/>
|
|
@@ -545,7 +556,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
545
556
|
</span>
|
|
546
557
|
<div class="flex shrink-0 items-center">
|
|
547
558
|
<!-- Companion toggle: attach/detach the dependent reviewer for this producer. -->
|
|
548
|
-
<
|
|
559
|
+
<IconButton
|
|
549
560
|
v-if="companionForProducer(unit.kind)"
|
|
550
561
|
:icon="
|
|
551
562
|
unit.companionIndex !== null ? 'i-lucide-scan-eye' : 'i-lucide-scan-search'
|
|
@@ -553,7 +564,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
553
564
|
:color="unit.companionIndex !== null ? 'secondary' : 'neutral'"
|
|
554
565
|
variant="ghost"
|
|
555
566
|
size="xs"
|
|
556
|
-
:
|
|
567
|
+
:label="
|
|
557
568
|
unit.companionIndex !== null
|
|
558
569
|
? t('pipeline.builder.companionRemove', {
|
|
559
570
|
companion: companionLabel(unit.kind),
|
|
@@ -565,7 +576,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
565
576
|
@click="pipelines.toggleCompanion(unit.index)"
|
|
566
577
|
/>
|
|
567
578
|
<!-- Enable/disable: keep the step in the pipeline but skip it at run. -->
|
|
568
|
-
<
|
|
579
|
+
<IconButton
|
|
569
580
|
:icon="
|
|
570
581
|
pipelines.draftEnabled[unit.index] === false
|
|
571
582
|
? 'i-lucide-eye-off'
|
|
@@ -574,7 +585,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
574
585
|
:color="pipelines.draftEnabled[unit.index] === false ? 'neutral' : 'primary'"
|
|
575
586
|
variant="ghost"
|
|
576
587
|
size="xs"
|
|
577
|
-
:
|
|
588
|
+
:label="
|
|
578
589
|
pipelines.draftEnabled[unit.index] === false
|
|
579
590
|
? t('pipeline.builder.enableTooltip')
|
|
580
591
|
: t('pipeline.builder.disableTooltip')
|
|
@@ -592,13 +603,13 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
592
603
|
so the engine holds it to the same gatability rule as an estimate gate
|
|
593
604
|
(`assertValidRunConditions`) — without this the builder invited a condition on
|
|
594
605
|
`merger` and answered the save with a 422. -->
|
|
595
|
-
<
|
|
606
|
+
<IconButton
|
|
596
607
|
v-if="mayCarrySkipAxis(unit.kind)"
|
|
597
608
|
:icon="CONDITION_ICONS[pipelines.draftStepCondition(unit.index) ?? 'always']"
|
|
598
609
|
:color="pipelines.draftStepCondition(unit.index) ? 'info' : 'neutral'"
|
|
599
610
|
variant="ghost"
|
|
600
611
|
size="xs"
|
|
601
|
-
:
|
|
612
|
+
:label="
|
|
602
613
|
t(
|
|
603
614
|
`pipeline.builder.condition.${pipelines.draftStepCondition(unit.index) ?? 'always'}`,
|
|
604
615
|
)
|
|
@@ -608,14 +619,14 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
608
619
|
/>
|
|
609
620
|
<!-- Approval gate: pause after this step so a human reviews (and
|
|
610
621
|
can edit) its proposal before the next step runs. -->
|
|
611
|
-
<
|
|
622
|
+
<IconButton
|
|
612
623
|
:icon="
|
|
613
624
|
pipelines.draftGates[unit.index] ? 'i-lucide-shield-check' : 'i-lucide-shield'
|
|
614
625
|
"
|
|
615
626
|
:color="pipelines.draftGates[unit.index] ? 'warning' : 'neutral'"
|
|
616
627
|
variant="ghost"
|
|
617
628
|
size="xs"
|
|
618
|
-
:
|
|
629
|
+
:label="
|
|
619
630
|
pipelines.draftGates[unit.index]
|
|
620
631
|
? t('pipeline.builder.approvalRemoveTooltip')
|
|
621
632
|
: t('pipeline.builder.approvalAddTooltip')
|
|
@@ -625,7 +636,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
625
636
|
/>
|
|
626
637
|
<!-- Consensus: run this step through the multi-model mechanism (eligible
|
|
627
638
|
kinds only — architect/analysis/task-estimator). -->
|
|
628
|
-
<
|
|
639
|
+
<IconButton
|
|
629
640
|
v-if="isConsensusEligibleKind(unit.kind)"
|
|
630
641
|
:icon="
|
|
631
642
|
pipelines.draftConsensus[unit.index]?.enabled
|
|
@@ -635,7 +646,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
635
646
|
:color="pipelines.draftConsensus[unit.index]?.enabled ? 'success' : 'neutral'"
|
|
636
647
|
variant="ghost"
|
|
637
648
|
size="xs"
|
|
638
|
-
:
|
|
649
|
+
:label="
|
|
639
650
|
pipelines.draftConsensus[unit.index]?.enabled
|
|
640
651
|
? t('pipeline.builder.consensusRevertTooltip')
|
|
641
652
|
: t('pipeline.builder.consensusEnableTooltip')
|
|
@@ -644,7 +655,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
644
655
|
/>
|
|
645
656
|
<!-- Follow-up companion: the future-looking Coder surfaces loose ends /
|
|
646
657
|
side-tasks / questions mid-run (coder steps only). Enabled by default. -->
|
|
647
|
-
<
|
|
658
|
+
<IconButton
|
|
648
659
|
v-if="unit.kind === 'coder'"
|
|
649
660
|
:icon="
|
|
650
661
|
pipelines.draftFollowUps[unit.index] === false
|
|
@@ -656,7 +667,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
656
667
|
"
|
|
657
668
|
variant="ghost"
|
|
658
669
|
size="xs"
|
|
659
|
-
:
|
|
670
|
+
:label="
|
|
660
671
|
pipelines.draftFollowUps[unit.index] === false
|
|
661
672
|
? t('pipeline.builder.followUpEnableTooltip')
|
|
662
673
|
: t('pipeline.builder.followUpDisableTooltip')
|
|
@@ -666,7 +677,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
666
677
|
<!-- Test quality-control companion: audits the Tester's report for coverage
|
|
667
678
|
before the greenlight/fixer decision and loops the Tester on gaps (Tester
|
|
668
679
|
steps only). Enabled by default. -->
|
|
669
|
-
<
|
|
680
|
+
<IconButton
|
|
670
681
|
v-if="isTesterKind(unit.kind)"
|
|
671
682
|
:icon="
|
|
672
683
|
pipelines.draftTesterQuality[unit.index]?.enabled === false
|
|
@@ -680,7 +691,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
680
691
|
"
|
|
681
692
|
variant="ghost"
|
|
682
693
|
size="xs"
|
|
683
|
-
:
|
|
694
|
+
:label="
|
|
684
695
|
pipelines.draftTesterQuality[unit.index]?.enabled === false
|
|
685
696
|
? t('pipeline.builder.testerQualityEnableTooltip')
|
|
686
697
|
: t('pipeline.builder.testerQualityDisableTooltip')
|
|
@@ -690,7 +701,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
690
701
|
<!-- Auto-recommendation: the requirements reviewer pre-answers findings it
|
|
691
702
|
judges answerable from universal practice / provided context, offering them
|
|
692
703
|
as editable default answers (requirements-review steps only). On by default. -->
|
|
693
|
-
<
|
|
704
|
+
<IconButton
|
|
694
705
|
v-if="unit.kind === 'requirements-review'"
|
|
695
706
|
:icon="
|
|
696
707
|
pipelines.draftAutoRecommendEnabled(unit.index)
|
|
@@ -702,7 +713,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
702
713
|
"
|
|
703
714
|
variant="ghost"
|
|
704
715
|
size="xs"
|
|
705
|
-
:
|
|
716
|
+
:label="
|
|
706
717
|
pipelines.draftAutoRecommendEnabled(unit.index)
|
|
707
718
|
? t('pipeline.builder.autoRecommendDisableTooltip')
|
|
708
719
|
: t('pipeline.builder.autoRecommendEnableTooltip')
|
|
@@ -713,7 +724,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
713
724
|
preview a reviewer pokes at after the PR is open. Off by default, and the
|
|
714
725
|
save boundary refuses a Deployer that neither reclaims nor declares this,
|
|
715
726
|
so the tick is how an unreclaimed environment says it is deliberate. -->
|
|
716
|
-
<
|
|
727
|
+
<IconButton
|
|
717
728
|
v-if="showRetainEnvironmentToggle(unit.kind, unit.index)"
|
|
718
729
|
:icon="
|
|
719
730
|
pipelines.draftRetainEnvironment(unit.index)
|
|
@@ -723,7 +734,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
723
734
|
:color="pipelines.draftRetainEnvironment(unit.index) ? 'warning' : 'neutral'"
|
|
724
735
|
variant="ghost"
|
|
725
736
|
size="xs"
|
|
726
|
-
:
|
|
737
|
+
:label="
|
|
727
738
|
pipelines.draftRetainEnvironment(unit.index)
|
|
728
739
|
? t('pipeline.builder.retainEnvironmentClearTooltip')
|
|
729
740
|
: t('pipeline.builder.retainEnvironmentSetTooltip')
|
|
@@ -732,43 +743,43 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
732
743
|
/>
|
|
733
744
|
<!-- System prompt: replace what this agent kind ships with, for every run in
|
|
734
745
|
this workspace, with the full revision history to switch back through. -->
|
|
735
|
-
<
|
|
746
|
+
<IconButton
|
|
736
747
|
v-if="showPromptEditor(unit.kind)"
|
|
737
748
|
icon="i-lucide-file-pen-line"
|
|
738
749
|
:color="agentPrompts.isCustomized(unit.kind) ? 'warning' : 'neutral'"
|
|
739
750
|
variant="ghost"
|
|
740
751
|
size="xs"
|
|
741
|
-
:
|
|
752
|
+
:label="
|
|
742
753
|
agentPrompts.isCustomized(unit.kind)
|
|
743
754
|
? t('pipeline.builder.promptEditedTooltip')
|
|
744
755
|
: t('pipeline.builder.promptEditTooltip')
|
|
745
756
|
"
|
|
746
757
|
@click="promptEditorKind = unit.kind"
|
|
747
758
|
/>
|
|
748
|
-
<
|
|
759
|
+
<IconButton
|
|
749
760
|
icon="i-lucide-chevron-up"
|
|
750
761
|
color="neutral"
|
|
751
762
|
variant="ghost"
|
|
752
763
|
size="xs"
|
|
753
|
-
:
|
|
764
|
+
:label="t('pipeline.builder.moveUp')"
|
|
754
765
|
:disabled="vi === 0"
|
|
755
766
|
@click="pipelines.moveUnit(vi, vi - 1)"
|
|
756
767
|
/>
|
|
757
|
-
<
|
|
768
|
+
<IconButton
|
|
758
769
|
icon="i-lucide-chevron-down"
|
|
759
770
|
color="neutral"
|
|
760
771
|
variant="ghost"
|
|
761
772
|
size="xs"
|
|
762
|
-
:
|
|
773
|
+
:label="t('pipeline.builder.moveDown')"
|
|
763
774
|
:disabled="vi === pipelines.units.length - 1"
|
|
764
775
|
@click="pipelines.moveUnit(vi, vi + 1)"
|
|
765
776
|
/>
|
|
766
|
-
<
|
|
777
|
+
<IconButton
|
|
767
778
|
icon="i-lucide-x"
|
|
768
779
|
color="error"
|
|
769
780
|
variant="ghost"
|
|
770
781
|
size="xs"
|
|
771
|
-
:
|
|
782
|
+
:label="t('pipeline.builder.removeStep')"
|
|
772
783
|
@click="removeUnit(unit)"
|
|
773
784
|
/>
|
|
774
785
|
</div>
|
|
@@ -873,7 +884,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
873
884
|
</span>
|
|
874
885
|
<!-- A companion is an agent kind with a prompt of its own, and this row is its
|
|
875
886
|
only route to it — so the affordance belongs here too, not only on producers. -->
|
|
876
|
-
<
|
|
887
|
+
<IconButton
|
|
877
888
|
v-if="showPromptEditor(pipelines.draft[unit.companionIndex]!)"
|
|
878
889
|
icon="i-lucide-file-pen-line"
|
|
879
890
|
:color="
|
|
@@ -883,7 +894,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
883
894
|
"
|
|
884
895
|
variant="ghost"
|
|
885
896
|
size="xs"
|
|
886
|
-
:
|
|
897
|
+
:label="
|
|
887
898
|
agentPrompts.isCustomized(pipelines.draft[unit.companionIndex]!)
|
|
888
899
|
? t('pipeline.builder.promptEditedTooltip')
|
|
889
900
|
: t('pipeline.builder.promptEditTooltip')
|
|
@@ -939,22 +950,23 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
939
950
|
{{ t('pipeline.builder.consensusGroupsHint') }}
|
|
940
951
|
</p>
|
|
941
952
|
<div class="flex flex-wrap gap-1">
|
|
942
|
-
<
|
|
953
|
+
<UButton
|
|
954
|
+
color="neutral"
|
|
955
|
+
variant="ghost"
|
|
943
956
|
v-for="group in consensusGroups.groups"
|
|
944
957
|
:key="group.id"
|
|
945
|
-
type="button"
|
|
946
958
|
class="rounded-sm border px-1.5 py-0.5 text-2xs"
|
|
947
959
|
:class="
|
|
948
960
|
isGroupSelected(unit.index, group.id)
|
|
949
|
-
? 'border-app-success-600 bg-app-success-900/40 text-app-success-200'
|
|
950
|
-
: 'border-muted bg-default text-muted hover:text-default'
|
|
961
|
+
? 'border-app-success-600 bg-app-success-900/40 hover:bg-app-success-900/40 focus-visible:bg-app-success-900/40 disabled:bg-app-success-900/40 text-app-success-200'
|
|
962
|
+
: 'border-muted bg-default hover:bg-default focus-visible:bg-default disabled:bg-default text-muted hover:text-default'
|
|
951
963
|
"
|
|
952
964
|
:title="group.description"
|
|
953
965
|
@click="pipelines.toggleDraftConsensusGroup(unit.index, group.id)"
|
|
954
966
|
>
|
|
955
967
|
{{ group.name }}
|
|
956
968
|
<span class="ms-1 text-dimmed">{{ groupBarLabel(group.id) }}</span>
|
|
957
|
-
</
|
|
969
|
+
</UButton>
|
|
958
970
|
</div>
|
|
959
971
|
</div>
|
|
960
972
|
|
|
@@ -965,27 +977,24 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
965
977
|
<template v-else>
|
|
966
978
|
<div class="flex items-center gap-2">
|
|
967
979
|
<label class="text-muted">{{ t('pipeline.builder.strategy') }}</label>
|
|
968
|
-
<
|
|
980
|
+
<USelect
|
|
969
981
|
v-model="pipelines.draftConsensus[unit.index]!.strategy"
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
{{ s.label }}
|
|
974
|
-
</option>
|
|
975
|
-
</select>
|
|
982
|
+
:items="CONSENSUS_STRATEGIES"
|
|
983
|
+
size="xs"
|
|
984
|
+
/>
|
|
976
985
|
<label
|
|
977
986
|
v-if="pipelines.draftConsensus[unit.index]!.strategy === 'debate'"
|
|
978
987
|
class="ms-2 text-muted"
|
|
979
988
|
>{{ t('pipeline.builder.rounds') }}</label
|
|
980
989
|
>
|
|
981
|
-
<
|
|
990
|
+
<UInputNumber
|
|
982
991
|
v-if="pipelines.draftConsensus[unit.index]!.strategy === 'debate'"
|
|
983
|
-
v-model.
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
max="5"
|
|
992
|
+
v-model.optional="pipelines.draftConsensus[unit.index]!.rounds"
|
|
993
|
+
:min="1"
|
|
994
|
+
:max="5"
|
|
987
995
|
placeholder="2"
|
|
988
|
-
|
|
996
|
+
size="xs"
|
|
997
|
+
class="w-24"
|
|
989
998
|
/>
|
|
990
999
|
</div>
|
|
991
1000
|
|
|
@@ -996,23 +1005,25 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
996
1005
|
:key="p.id"
|
|
997
1006
|
class="flex items-center gap-1.5"
|
|
998
1007
|
>
|
|
999
|
-
<
|
|
1008
|
+
<UInput
|
|
1000
1009
|
v-model="p.role"
|
|
1010
|
+
size="xs"
|
|
1011
|
+
class="w-28"
|
|
1001
1012
|
:placeholder="t('pipeline.builder.rolePlaceholder')"
|
|
1002
|
-
class="w-28 rounded-sm border border-muted bg-default px-1.5 py-0.5 text-app-100"
|
|
1003
1013
|
/>
|
|
1004
|
-
<
|
|
1014
|
+
<UInput
|
|
1005
1015
|
v-model="p.modelId"
|
|
1016
|
+
size="xs"
|
|
1017
|
+
class="flex-1"
|
|
1006
1018
|
:placeholder="t('pipeline.builder.modelIdPlaceholder')"
|
|
1007
|
-
class="flex-1 rounded-sm border border-muted bg-default px-1.5 py-0.5 text-toned"
|
|
1008
1019
|
/>
|
|
1009
|
-
<
|
|
1020
|
+
<IconButton
|
|
1010
1021
|
icon="i-lucide-x"
|
|
1011
1022
|
color="error"
|
|
1012
1023
|
variant="ghost"
|
|
1013
1024
|
size="xs"
|
|
1014
1025
|
:disabled="pipelines.draftConsensus[unit.index]!.participants.length <= 2"
|
|
1015
|
-
:
|
|
1026
|
+
:label="t('pipeline.builder.removeParticipant')"
|
|
1016
1027
|
@click="removeParticipant(unit.index, pIdx)"
|
|
1017
1028
|
/>
|
|
1018
1029
|
</div>
|
|
@@ -1171,9 +1182,10 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
1171
1182
|
)
|
|
1172
1183
|
}}
|
|
1173
1184
|
</span>
|
|
1174
|
-
<
|
|
1175
|
-
|
|
1176
|
-
|
|
1185
|
+
<UButton
|
|
1186
|
+
color="neutral"
|
|
1187
|
+
variant="link"
|
|
1188
|
+
class="p-0 text-3xs underline underline-offset-2 hover:text-toned"
|
|
1177
1189
|
data-testid="pipeline-library-purpose-toggle"
|
|
1178
1190
|
@click="browseEveryPurpose = !browseEveryPurpose"
|
|
1179
1191
|
>
|
|
@@ -1182,7 +1194,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
1182
1194
|
? t('pipeline.builder.narrowToDraftPurpose')
|
|
1183
1195
|
: t('pipeline.builder.listEveryPurpose')
|
|
1184
1196
|
}}
|
|
1185
|
-
</
|
|
1197
|
+
</UButton>
|
|
1186
1198
|
</div>
|
|
1187
1199
|
|
|
1188
1200
|
<ul class="flex-1 space-y-1.5 pe-1 lg:min-h-0 lg:overflow-y-auto">
|
|
@@ -1193,9 +1205,10 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
1193
1205
|
:class="{ 'opacity-60': p.archived }"
|
|
1194
1206
|
>
|
|
1195
1207
|
<div class="flex items-center gap-2 px-2 py-1.5">
|
|
1196
|
-
<
|
|
1197
|
-
|
|
1198
|
-
|
|
1208
|
+
<UButton
|
|
1209
|
+
color="neutral"
|
|
1210
|
+
variant="ghost"
|
|
1211
|
+
class="flex min-w-0 flex-1 items-center gap-2 p-0 text-start hover:bg-transparent"
|
|
1199
1212
|
@click="toggleSaved(p.id)"
|
|
1200
1213
|
>
|
|
1201
1214
|
<UIcon
|
|
@@ -1259,7 +1272,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
1259
1272
|
)
|
|
1260
1273
|
}}
|
|
1261
1274
|
</span>
|
|
1262
|
-
</
|
|
1275
|
+
</UButton>
|
|
1263
1276
|
<div
|
|
1264
1277
|
class="flex shrink-0 items-center opacity-0 transition group-hover:opacity-100"
|
|
1265
1278
|
>
|
|
@@ -1270,24 +1283,24 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
1270
1283
|
ARCHIVING a row that still holds one: a hidden row never holds a default,
|
|
1271
1284
|
so there is never one here to release. -->
|
|
1272
1285
|
<template v-if="uiMode.isAdvanced && !p.archived && !p.internal">
|
|
1273
|
-
<
|
|
1286
|
+
<IconButton
|
|
1274
1287
|
:icon="p.isDefault ? 'i-lucide-star' : 'i-lucide-star-off'"
|
|
1275
1288
|
:color="p.isDefault ? 'primary' : 'neutral'"
|
|
1276
1289
|
variant="ghost"
|
|
1277
1290
|
size="xs"
|
|
1278
|
-
:
|
|
1291
|
+
:label="
|
|
1279
1292
|
p.isDefault
|
|
1280
1293
|
? t('pipeline.builder.scopeDefault.releaseInteractive')
|
|
1281
1294
|
: t('pipeline.builder.scopeDefault.claimInteractive')
|
|
1282
1295
|
"
|
|
1283
1296
|
@click="toggleDefault(p, 'interactive')"
|
|
1284
1297
|
/>
|
|
1285
|
-
<
|
|
1298
|
+
<IconButton
|
|
1286
1299
|
:icon="p.isUnattendedDefault ? 'i-lucide-bot' : 'i-lucide-bot-off'"
|
|
1287
1300
|
:color="p.isUnattendedDefault ? 'info' : 'neutral'"
|
|
1288
1301
|
variant="ghost"
|
|
1289
1302
|
size="xs"
|
|
1290
|
-
:
|
|
1303
|
+
:label="
|
|
1291
1304
|
p.isUnattendedDefault
|
|
1292
1305
|
? t('pipeline.builder.scopeDefault.releaseUnattended')
|
|
1293
1306
|
: t('pipeline.builder.scopeDefault.claimUnattended')
|
|
@@ -1297,47 +1310,47 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
1297
1310
|
</template>
|
|
1298
1311
|
<!-- Archive/unarchive: organize the library without deleting. Works on
|
|
1299
1312
|
built-ins too (view metadata, not structure). -->
|
|
1300
|
-
<
|
|
1313
|
+
<IconButton
|
|
1301
1314
|
:icon="p.archived ? 'i-lucide-archive-restore' : 'i-lucide-archive'"
|
|
1302
1315
|
color="neutral"
|
|
1303
1316
|
variant="ghost"
|
|
1304
1317
|
size="xs"
|
|
1305
|
-
:
|
|
1318
|
+
:label="
|
|
1306
1319
|
p.archived ? t('pipeline.builder.unarchive') : t('pipeline.builder.archive')
|
|
1307
1320
|
"
|
|
1308
1321
|
@click="toggleArchive(p)"
|
|
1309
1322
|
/>
|
|
1310
1323
|
<!-- Clone is available on every pipeline — it's how a read-only
|
|
1311
1324
|
built-in template becomes an editable copy. -->
|
|
1312
|
-
<
|
|
1325
|
+
<IconButton
|
|
1313
1326
|
icon="i-lucide-copy"
|
|
1314
1327
|
color="neutral"
|
|
1315
1328
|
variant="ghost"
|
|
1316
1329
|
size="xs"
|
|
1317
|
-
:
|
|
1330
|
+
:label="
|
|
1318
1331
|
p.builtin ? t('pipeline.builder.cloneDefault') : t('pipeline.builder.clone')
|
|
1319
1332
|
"
|
|
1320
1333
|
@click="clone(p)"
|
|
1321
1334
|
/>
|
|
1322
1335
|
<!-- Built-in templates are read-only; only custom pipelines edit in place. -->
|
|
1323
|
-
<
|
|
1336
|
+
<IconButton
|
|
1324
1337
|
v-if="!p.builtin"
|
|
1325
1338
|
icon="i-lucide-pencil"
|
|
1326
1339
|
color="neutral"
|
|
1327
1340
|
variant="ghost"
|
|
1328
1341
|
size="xs"
|
|
1329
|
-
:
|
|
1342
|
+
:label="t('pipeline.builder.edit')"
|
|
1330
1343
|
@click="edit(p)"
|
|
1331
1344
|
/>
|
|
1332
1345
|
<!-- Built-in templates are read-only — they can be cloned but not
|
|
1333
1346
|
deleted (the backend rejects it too); only custom ones delete. -->
|
|
1334
|
-
<
|
|
1347
|
+
<IconButton
|
|
1335
1348
|
v-if="!p.builtin"
|
|
1336
1349
|
icon="i-lucide-trash-2"
|
|
1337
1350
|
color="neutral"
|
|
1338
1351
|
variant="ghost"
|
|
1339
1352
|
size="xs"
|
|
1340
|
-
:
|
|
1353
|
+
:label="t('pipeline.builder.delete')"
|
|
1341
1354
|
@click="removePipeline(p)"
|
|
1342
1355
|
/>
|
|
1343
1356
|
</div>
|