@cat-factory/app 0.308.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 +32 -2
- package/app/assets/css/main.css +22 -0
- package/app/assets/css/prose.css +4 -4
- package/app/assets/css/type.css +24 -0
- package/app/components/assistant/AssistantModal.vue +8 -6
- 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 +5 -4
- package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +48 -37
- package/app/components/binaryOutput/BinaryOutputReport.vue +10 -14
- package/app/components/binaryOutput/StoredAssetView.vue +13 -11
- package/app/components/board/AddTaskModal.vue +30 -27
- package/app/components/board/AgentFailureCard.vue +21 -18
- package/app/components/board/AgentFailureHistory.vue +18 -9
- package/app/components/board/CreateInitiativeModal.vue +7 -6
- package/app/components/board/FailureDetail.vue +22 -12
- package/app/components/board/FailureHistoryList.vue +5 -5
- package/app/components/board/RecurringPipelineModal.vue +12 -11
- package/app/components/board/ReviewFrictionDialog.vue +8 -6
- package/app/components/board/StepExecutionHistory.vue +8 -8
- package/app/components/board/nodes/AgentChip.vue +1 -1
- package/app/components/board/nodes/BlockNode.vue +25 -24
- package/app/components/board/nodes/DecisionBadge.vue +4 -3
- package/app/components/board/nodes/EpicNode.vue +4 -4
- package/app/components/board/nodes/FrameSwimlanes.vue +8 -10
- package/app/components/board/nodes/InitiativeCard.vue +4 -4
- package/app/components/board/nodes/LaneGroup.vue +3 -5
- package/app/components/board/nodes/TaskCard.vue +20 -15
- package/app/components/board/nodes/TaskLane.vue +3 -3
- package/app/components/board/nodes/TaskPipelineMini.vue +21 -18
- package/app/components/bootstrap/AdoptionReviewModal.vue +36 -26
- package/app/components/bootstrap/BootstrapModal.vue +14 -13
- package/app/components/bootstrap/BootstrapRunSteps.vue +1 -1
- package/app/components/brainstorm/BrainstormWindow.vue +13 -10
- package/app/components/bugFishing/BugFishingWindow.vue +81 -58
- package/app/components/clarity/ClarityReviewWindow.vue +13 -10
- package/app/components/common/AsyncViewError.vue +1 -1
- package/app/components/common/ClarificationItem.vue +6 -6
- package/app/components/common/CopyButton.vue +12 -11
- package/app/components/common/DescriptorFields.vue +1 -1
- package/app/components/common/EmptyState.vue +1 -1
- package/app/components/common/IconButton.vue +34 -9
- package/app/components/common/InterviewGateNotice.vue +4 -4
- package/app/components/common/MarkdownProse.vue +8 -2
- package/app/components/common/SectionLabel.vue +38 -0
- package/app/components/consensus/ConsensusSessionWindow.vue +10 -9
- package/app/components/context/ContextAttachmentFields.vue +32 -20
- package/app/components/docs/DocInterviewWindow.vue +10 -9
- package/app/components/documents/ContextDocumentPicker.vue +22 -21
- package/app/components/documents/DocumentImportModal.vue +7 -5
- package/app/components/documents/DocumentOriginLink.vue +12 -9
- package/app/components/documents/DocumentSourceConnectModal.vue +2 -2
- package/app/components/documents/DocumentSyncState.vue +4 -4
- package/app/components/documents/DocumentTemplatesModal.vue +5 -4
- package/app/components/documents/RepoContextDocPicker.vue +7 -9
- package/app/components/documents/StartFromDesignModal.vue +4 -4
- package/app/components/documents/TaskContextDocs.vue +1 -1
- package/app/components/environments/EnvSetupStepper.vue +3 -3
- package/app/components/environments/EnvironmentStatusPanel.vue +15 -13
- package/app/components/environments/steps/EnvPreflightStep.vue +8 -8
- package/app/components/environments/steps/EnvReviewStep.vue +23 -22
- package/app/components/environments/steps/EnvSaveStep.vue +5 -5
- package/app/components/focus/BlockFocusView.vue +11 -10
- package/app/components/followUp/FollowUpWindow.vue +18 -15
- package/app/components/forkDecision/ForkDecisionWindow.vue +85 -97
- package/app/components/foundational/FoundationalContractSummary.vue +2 -2
- package/app/components/foundational/FoundationalServiceCatalogList.vue +6 -5
- package/app/components/foundational/FoundationalServiceRegistry.vue +10 -9
- package/app/components/foundational/FoundationalServiceSources.vue +7 -6
- package/app/components/foundational/FoundationalSuppressions.vue +2 -2
- package/app/components/fragments/FragmentLibraryManager.vue +8 -7
- package/app/components/fragments/FragmentSelector.vue +22 -20
- package/app/components/gates/GateFailingCheckList.vue +7 -6
- package/app/components/gates/GateResultView.vue +55 -49
- package/app/components/github/AddServiceFromRepoModal.vue +16 -11
- package/app/components/github/BranchProtectionPreflight.vue +5 -5
- package/app/components/github/GitHubConnect.vue +5 -3
- package/app/components/github/GitHubOnboarding.vue +7 -2
- package/app/components/github/GitHubPanel.vue +23 -19
- package/app/components/github/RepoTreeBrowser.vue +16 -13
- package/app/components/humanTest/HumanTestWindow.vue +29 -24
- package/app/components/initiative/InitiativePlanNotice.vue +3 -3
- package/app/components/initiative/InitiativePlanReview.vue +46 -38
- package/app/components/initiative/InitiativePlanningWindow.vue +5 -5
- package/app/components/initiative/InitiativeTrackerWindow.vue +213 -165
- package/app/components/judge/JudgeResultView.vue +28 -27
- package/app/components/kaizen/KaizenPanel.vue +70 -56
- package/app/components/kaizen/KaizenStepStatus.vue +7 -6
- package/app/components/layout/AccountAuditLog.vue +1 -1
- package/app/components/layout/AccountDeploymentSettings.vue +10 -10
- package/app/components/layout/AccountFailureKindRules.vue +13 -13
- package/app/components/layout/AccountFoundationalSettings.vue +1 -1
- package/app/components/layout/AccountFragmentSettings.vue +1 -1
- package/app/components/layout/AccountModelPolicySettings.vue +7 -7
- package/app/components/layout/AccountPlatformAlertSettings.vue +8 -8
- package/app/components/layout/AccountRiskPolicySettings.vue +2 -2
- package/app/components/layout/AccountRunCredentialSettings.vue +3 -3
- package/app/components/layout/AccountSkillSettings.vue +1 -1
- package/app/components/layout/AccountTeamSettings.vue +13 -9
- package/app/components/layout/AiProvidersBanner.vue +1 -1
- package/app/components/layout/AppearanceSwitcher.vue +5 -4
- package/app/components/layout/BoardSwitcher.vue +13 -10
- package/app/components/layout/BoardToolbar.vue +10 -5
- package/app/components/layout/CommandBar.vue +8 -5
- package/app/components/layout/DefaultTestEnvBanner.vue +6 -5
- package/app/components/layout/IntegrationsHub.vue +12 -9
- package/app/components/layout/LanguageSwitcher.vue +5 -4
- package/app/components/layout/ModelProvidersHub.vue +10 -7
- package/app/components/layout/NotificationsInbox.vue +47 -36
- package/app/components/layout/PersonalSetupModal.vue +9 -6
- package/app/components/layout/RolePrompt.vue +5 -4
- package/app/components/layout/SideBar.vue +7 -8
- package/app/components/layout/SpendWarningBanner.vue +3 -3
- package/app/components/layout/TranslationWarningBanner.vue +5 -4
- package/app/components/layout/UiModeSwitcher.vue +15 -12
- package/app/components/layout/UiRoleSwitcher.vue +10 -8
- package/app/components/layout/WorkspaceMembersSettings.vue +2 -2
- package/app/components/media/ArtifactLightbox.vue +74 -44
- package/app/components/media/ImageCompare.vue +80 -85
- package/app/components/merge/MergeEffortChips.vue +4 -6
- package/app/components/notifications/NotificationSettingsPanel.vue +6 -5
- package/app/components/observability/OutcomeFilterChips.vue +6 -5
- package/app/components/observability/RunFailureSummary.vue +22 -23
- package/app/components/observability/StepMetricsBar.vue +9 -8
- package/app/components/observability/StepModelActivity.vue +8 -5
- package/app/components/observability/ToolCallList.vue +19 -20
- package/app/components/outcome/OutcomeSummaryWindow.vue +48 -46
- package/app/components/palettes/AgentPalette.vue +21 -15
- package/app/components/palettes/AgentTierSelect.vue +1 -1
- package/app/components/palettes/PipelinePurposeSelect.vue +1 -1
- package/app/components/panels/AgentStepDetail.vue +57 -49
- package/app/components/panels/AttemptEntryHeader.vue +2 -2
- package/app/components/panels/DecisionModal.vue +1 -1
- package/app/components/panels/GenericStructuredResultView.vue +6 -5
- package/app/components/panels/InspectorPanel.vue +15 -13
- package/app/components/panels/MergerResultView.vue +10 -9
- package/app/components/panels/ObservabilityPanel.vue +211 -186
- package/app/components/panels/OperatorDashboardPanel.vue +124 -115
- package/app/components/panels/ReportsPanel.vue +87 -83
- package/app/components/panels/ReportsSpendBreakdown.vue +2 -2
- package/app/components/panels/ResultWindowShell.vue +152 -137
- package/app/components/panels/RunDetailLoadState.vue +1 -1
- package/app/components/panels/StepContainerStatus.vue +17 -16
- package/app/components/panels/StepDelegatedStatus.vue +24 -21
- package/app/components/panels/StepEffortReport.vue +12 -17
- package/app/components/panels/StepFragmentAdherence.vue +9 -10
- package/app/components/panels/StepMetadataCard.vue +41 -43
- package/app/components/panels/StepReproductionReport.vue +18 -20
- package/app/components/panels/StepRestartControl.vue +3 -2
- package/app/components/panels/StepRunMeta.vue +27 -26
- package/app/components/panels/StepTestReport.vue +16 -15
- package/app/components/panels/StepToolServers.vue +7 -8
- package/app/components/panels/StepValidationReport.vue +5 -5
- package/app/components/panels/inspector/ContainerSummary.vue +4 -4
- package/app/components/panels/inspector/DocReferenceRepos.vue +5 -4
- package/app/components/panels/inspector/EnvProbeReport.vue +16 -13
- package/app/components/panels/inspector/EpicChildren.vue +12 -10
- package/app/components/panels/inspector/FrontendBindingsResolved.vue +5 -4
- package/app/components/panels/inspector/FrontendConfig.vue +29 -36
- package/app/components/panels/inspector/InitiativeInspector.vue +3 -3
- package/app/components/panels/inspector/InspectorSection.vue +25 -17
- package/app/components/panels/inspector/RecurringScheduleSettings.vue +9 -8
- package/app/components/panels/inspector/ServiceConnections.vue +5 -4
- package/app/components/panels/inspector/ServiceReleaseHealthConfig.vue +2 -2
- package/app/components/panels/inspector/ServiceSelfTests.vue +9 -13
- package/app/components/panels/inspector/ServiceTestConfig.vue +46 -49
- package/app/components/panels/inspector/ServiceTestSecrets.vue +3 -3
- package/app/components/panels/inspector/ServiceTestingContext.vue +2 -2
- package/app/components/panels/inspector/ServiceValidationConfig.vue +2 -2
- package/app/components/panels/inspector/TaskAgentConfig.vue +2 -2
- package/app/components/panels/inspector/TaskAprioriBranches.vue +6 -5
- package/app/components/panels/inspector/TaskDependencies.vue +1 -1
- package/app/components/panels/inspector/TaskEstimateBadge.vue +3 -7
- package/app/components/panels/inspector/TaskExecution.vue +18 -16
- package/app/components/panels/inspector/TaskRunSettings.vue +45 -44
- package/app/components/panels/inspector/TaskStructure.vue +5 -4
- package/app/components/pipeline/AgentPromptEditor.vue +15 -14
- package/app/components/pipeline/BinaryOutputStepPicker.vue +42 -52
- package/app/components/pipeline/EstimateThresholdFields.vue +14 -11
- package/app/components/pipeline/GateConfigFields.vue +19 -23
- package/app/components/pipeline/IterationCapPrompt.vue +1 -1
- package/app/components/pipeline/PipelineBuilder.vue +113 -99
- package/app/components/pipeline/PipelineHealthModal.vue +7 -7
- package/app/components/pipeline/PipelinePicker.vue +11 -9
- package/app/components/pipeline/PipelinePreview.vue +6 -7
- package/app/components/pipeline/PipelineProgress.vue +49 -45
- package/app/components/prReview/PrReviewWindow.vue +87 -65
- package/app/components/providers/AiPresetMismatchDialog.vue +4 -3
- package/app/components/providers/AiProviderOnboardingModal.vue +2 -2
- package/app/components/providers/ApiKeysSection.vue +11 -9
- package/app/components/providers/PersonalSubscriptionSection.vue +4 -3
- package/app/components/providers/VendorCredentialsModal.vue +5 -4
- package/app/components/provisioning/ProvisioningLogsDrawer.vue +10 -9
- package/app/components/ralph/RalphLoopResultView.vue +29 -29
- package/app/components/requirements/RequirementsReviewWindow.vue +22 -17
- package/app/components/riskPolicy/RiskPolicyPicker.vue +13 -11
- package/app/components/riskPolicy/RiskPolicyPreview.vue +16 -15
- package/app/components/sandbox/SandboxPanel.vue +93 -73
- package/app/components/settings/ApiTokensPanel.vue +1 -1
- package/app/components/settings/BudgetSettings.vue +18 -17
- package/app/components/settings/CapabilityCredentialsPanel.vue +5 -5
- package/app/components/settings/CloudflareHandlerSection.vue +44 -41
- package/app/components/settings/ComposeEnvironmentSetupSection.vue +14 -12
- package/app/components/settings/ConnectionTestVerdict.vue +1 -1
- package/app/components/settings/ConsensusGroupsSection.vue +58 -47
- package/app/components/settings/CustomManifestTypeEditor.vue +8 -7
- package/app/components/settings/DefaultProvisionTypeSection.vue +5 -5
- package/app/components/settings/InfraHandlersConfigurator.vue +26 -24
- package/app/components/settings/InfrastructureBackendPicker.vue +18 -18
- package/app/components/settings/IssueTrackerPanel.vue +30 -21
- package/app/components/settings/KubernetesEngineForm.vue +9 -8
- package/app/components/settings/KubernetesEnvironmentForm.vue +4 -3
- package/app/components/settings/LocalContainerPoolSettings.vue +2 -2
- package/app/components/settings/LocalModelEndpointsPanel.vue +13 -11
- package/app/components/settings/MergeClassRulesEditor.vue +6 -5
- package/app/components/settings/MergeRolePolicyEditor.vue +13 -12
- package/app/components/settings/ModelConfigurationPanel.vue +17 -19
- package/app/components/settings/ModelPresetHealthModal.vue +3 -3
- package/app/components/settings/ObservabilityConnectionPanel.vue +1 -1
- package/app/components/settings/OpenRouterCatalogPanel.vue +10 -8
- package/app/components/settings/PackageRegistriesPanel.vue +4 -4
- package/app/components/settings/ProviderConnectionTab.vue +5 -4
- package/app/components/settings/ProviderManifestEditor.vue +9 -8
- package/app/components/settings/ProviderPreferenceEditor.vue +13 -13
- package/app/components/settings/RiskPolicyCreateForm.vue +40 -26
- package/app/components/settings/RiskPolicyEditorRow.vue +21 -19
- package/app/components/settings/RiskPolicyHealthModal.vue +3 -3
- package/app/components/settings/RiskPolicyPanel.vue +11 -13
- package/app/components/settings/ServiceFragmentDefaultsPanel.vue +15 -12
- package/app/components/settings/SharedStacksPanel.vue +5 -5
- package/app/components/settings/TaskSourceCard.vue +2 -2
- package/app/components/settings/TaskTypeSuppressionsPanel.vue +4 -4
- package/app/components/settings/ToolServerChecklist.vue +22 -22
- package/app/components/settings/UsageSettings.vue +13 -13
- package/app/components/settings/UserSecretsSection.vue +4 -3
- package/app/components/settings/WorkspaceMetadataSettings.vue +6 -5
- package/app/components/settings/WorkspaceSettingsPanel.vue +72 -58
- package/app/components/skills/ReviewSkillQueue.vue +12 -10
- package/app/components/skills/SkillLibraryManager.vue +9 -8
- package/app/components/slack/SlackPanel.vue +17 -12
- package/app/components/spec/ServiceSpecWindow.vue +19 -19
- package/app/components/tasks/BugHuntModal.vue +1 -1
- package/app/components/tasks/ContextIssuePicker.vue +16 -15
- package/app/components/tasks/TaskContextIssues.vue +5 -4
- package/app/components/tasks/TaskImportModal.vue +3 -2
- package/app/components/tasks/TaskSourceConnectModal.vue +5 -5
- package/app/components/testing/TestReportWindow.vue +67 -60
- package/app/components/theme/ThemeImportModal.vue +2 -2
- package/app/components/tutorial/TutorialNudge.vue +3 -2
- package/app/components/tutorial/TutorialOverlay.vue +3 -2
- package/app/components/vcs/GitLabConnect.vue +1 -1
- package/app/components/visualConfirm/VisualConfirmationWindow.vue +79 -54
- package/app/utils/theme/builtins.ts +7 -1
- 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
|
@@ -64,6 +64,12 @@ const canChat = computed(() => awaiting.value && !chatBudgetSpent.value && !fork
|
|
|
64
64
|
|
|
65
65
|
// The human's selection: a proposed fork id, or the sentinel 'custom' for the free-text path.
|
|
66
66
|
const selected = ref<string | null>(null)
|
|
67
|
+
// The proposed forks and "my own approach" are one choice, so they are one item list. `fork` is
|
|
68
|
+
// null on the custom entry, which is what the label and description slots branch on.
|
|
69
|
+
const forkItems = computed(() => [
|
|
70
|
+
...forks.value.map((fork) => ({ value: fork.id, label: fork.title, fork })),
|
|
71
|
+
{ value: 'custom', label: t('forkDecision.custom.title'), fork: null as ForkOption | null },
|
|
72
|
+
])
|
|
67
73
|
const customText = ref('')
|
|
68
74
|
const note = ref('')
|
|
69
75
|
const chatInput = ref('')
|
|
@@ -166,7 +172,7 @@ const { requestClose } = useUnsavedGuard({
|
|
|
166
172
|
>
|
|
167
173
|
<UIcon name="i-lucide-loader-circle" class="h-8 w-8 animate-spin opacity-60" />
|
|
168
174
|
<p class="text-sm">{{ t('forkDecision.proposing.title') }}</p>
|
|
169
|
-
<p class="max-w-sm text-
|
|
175
|
+
<p class="max-w-sm text-2xs text-dimmed">
|
|
170
176
|
{{ t('forkDecision.proposing.hint') }}
|
|
171
177
|
</p>
|
|
172
178
|
</div>
|
|
@@ -176,10 +182,10 @@ const { requestClose } = useUnsavedGuard({
|
|
|
176
182
|
v-else-if="status === 'single_path'"
|
|
177
183
|
class="rounded-xl border border-default bg-default/60 px-4 py-3 text-toned"
|
|
178
184
|
>
|
|
179
|
-
<p class="text-
|
|
185
|
+
<p class="text-sm font-medium text-app-100">
|
|
180
186
|
{{ t('forkDecision.singlePath.title') }}
|
|
181
187
|
</p>
|
|
182
|
-
<p v-if="state?.singlePathReason" class="mt-1 text-
|
|
188
|
+
<p v-if="state?.singlePathReason" class="mt-1 text-xs">
|
|
183
189
|
{{ state.singlePathReason }}
|
|
184
190
|
</p>
|
|
185
191
|
</div>
|
|
@@ -189,16 +195,16 @@ const { requestClose } = useUnsavedGuard({
|
|
|
189
195
|
v-else-if="status === 'chosen'"
|
|
190
196
|
class="rounded-xl border border-app-secondary-500/40 bg-default/60 px-4 py-3 text-toned"
|
|
191
197
|
>
|
|
192
|
-
<p class="text-
|
|
198
|
+
<p class="text-sm font-medium text-app-secondary-200">
|
|
193
199
|
{{ t('forkDecision.chosen.title') }}
|
|
194
200
|
</p>
|
|
195
|
-
<p v-if="state?.chosen?.custom" class="mt-1 whitespace-pre-wrap text-
|
|
201
|
+
<p v-if="state?.chosen?.custom" class="mt-1 whitespace-pre-wrap text-xs">
|
|
196
202
|
{{ state.chosen.custom }}
|
|
197
203
|
</p>
|
|
198
|
-
<p v-else-if="state?.chosen?.forkId" class="mt-1 text-
|
|
204
|
+
<p v-else-if="state?.chosen?.forkId" class="mt-1 text-xs">
|
|
199
205
|
{{ forks.find((f) => f.id === state?.chosen?.forkId)?.title }}
|
|
200
206
|
</p>
|
|
201
|
-
<p v-if="state?.chosen?.note" class="mt-1 text-
|
|
207
|
+
<p v-if="state?.chosen?.note" class="mt-1 text-2xs text-muted">
|
|
202
208
|
{{ t('forkDecision.chosen.note', { note: state.chosen.note }) }}
|
|
203
209
|
</p>
|
|
204
210
|
</div>
|
|
@@ -207,110 +213,90 @@ const { requestClose } = useUnsavedGuard({
|
|
|
207
213
|
<div v-else-if="interactive" class="space-y-3">
|
|
208
214
|
<p
|
|
209
215
|
v-if="forkDecision.error"
|
|
210
|
-
class="rounded-md bg-app-error-500/10 px-3 py-2 text-
|
|
216
|
+
class="rounded-md bg-app-error-500/10 px-3 py-2 text-xs text-app-error-300"
|
|
211
217
|
>
|
|
212
218
|
{{ forkDecision.error }}
|
|
213
219
|
</p>
|
|
214
220
|
|
|
215
|
-
<p
|
|
216
|
-
v-if="state?.seamSummary"
|
|
217
|
-
class="rounded-md bg-elevated/50 px-3 py-2 text-[12px] text-toned"
|
|
218
|
-
>
|
|
221
|
+
<p v-if="state?.seamSummary" class="rounded-md bg-elevated/50 px-3 py-2 text-xs text-toned">
|
|
219
222
|
<span class="text-dimmed">{{ t('forkDecision.seam') }}</span>
|
|
220
223
|
{{ state.seamSummary }}
|
|
221
224
|
</p>
|
|
222
225
|
|
|
223
|
-
<!--
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
"
|
|
234
|
-
@click="selected = fork.id"
|
|
226
|
+
<!-- The proposed forks and "my own approach" are ONE choice, so they are one radio
|
|
227
|
+
group rather than a set of cards each holding their own radio. `variant="card"`
|
|
228
|
+
is the shape these already had; the rich body rides the description slot. -->
|
|
229
|
+
<URadioGroup
|
|
230
|
+
:model-value="selected ?? undefined"
|
|
231
|
+
color="secondary"
|
|
232
|
+
variant="card"
|
|
233
|
+
:items="forkItems"
|
|
234
|
+
data-testid="fork-options"
|
|
235
|
+
:ui="{ item: 'px-4 py-3' }"
|
|
236
|
+
@update:model-value="selected = String($event)"
|
|
235
237
|
>
|
|
236
|
-
<
|
|
237
|
-
<
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
</
|
|
252
|
-
<
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
<p class="mt-1.5 whitespace-pre-wrap text-[12px] text-toned">
|
|
256
|
-
{{ fork.approach }}
|
|
257
|
-
</p>
|
|
258
|
-
<ul v-if="fork.tradeoffs.length" class="mt-1.5 space-y-0.5">
|
|
259
|
-
<li
|
|
260
|
-
v-for="(tr, i) in fork.tradeoffs"
|
|
238
|
+
<template #label="{ item }">
|
|
239
|
+
<span class="flex items-center gap-2">
|
|
240
|
+
<span class="min-w-0 flex-1 text-sm font-medium text-app-100">{{ item.label }}</span>
|
|
241
|
+
<UBadge v-if="item.fork?.recommended" color="primary" variant="subtle" size="sm">
|
|
242
|
+
{{ t('forkDecision.recommended') }}
|
|
243
|
+
</UBadge>
|
|
244
|
+
</span>
|
|
245
|
+
</template>
|
|
246
|
+
<template #description="{ item }">
|
|
247
|
+
<template v-if="item.fork">
|
|
248
|
+
<span v-if="item.fork.summary" class="block text-xs text-muted">
|
|
249
|
+
{{ item.fork.summary }}
|
|
250
|
+
</span>
|
|
251
|
+
<span class="mt-1.5 block whitespace-pre-wrap text-xs text-toned">
|
|
252
|
+
{{ item.fork.approach }}
|
|
253
|
+
</span>
|
|
254
|
+
<span v-if="item.fork.tradeoffs.length" class="mt-1.5 block space-y-0.5">
|
|
255
|
+
<span
|
|
256
|
+
v-for="(tr, i) in item.fork.tradeoffs"
|
|
261
257
|
:key="i"
|
|
262
|
-
class="flex gap-1.5 text-
|
|
258
|
+
class="flex gap-1.5 text-2xs text-muted"
|
|
263
259
|
>
|
|
264
260
|
<span class="text-app-600">•</span>{{ tr }}
|
|
265
|
-
</
|
|
266
|
-
</
|
|
267
|
-
<
|
|
261
|
+
</span>
|
|
262
|
+
</span>
|
|
263
|
+
<span
|
|
264
|
+
v-if="item.fork.riskNotes"
|
|
265
|
+
class="mt-1.5 block text-2xs text-app-warning-300/90"
|
|
266
|
+
>
|
|
268
267
|
<span class="text-app-warning-500/70">{{ t('forkDecision.riskNotes') }}</span>
|
|
269
|
-
{{ fork.riskNotes }}
|
|
270
|
-
</
|
|
271
|
-
</
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
<input type="radio" class="accent-app-secondary-500" :checked="selected === 'custom'" />
|
|
286
|
-
<span class="text-[13px] font-medium text-app-100">{{
|
|
287
|
-
t('forkDecision.custom.title')
|
|
288
|
-
}}</span>
|
|
289
|
-
</label>
|
|
290
|
-
<textarea
|
|
291
|
-
v-model="customText"
|
|
292
|
-
data-testid="fork-custom-input"
|
|
293
|
-
rows="3"
|
|
294
|
-
:placeholder="t('forkDecision.custom.placeholder')"
|
|
295
|
-
class="mt-2 w-full resize-y rounded-md border border-muted bg-app-950/60 px-2.5 py-1.5 text-[12px] text-app-100 placeholder:text-app-600 focus:border-app-secondary-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-app-secondary-500/60"
|
|
296
|
-
@focus="selected = 'custom'"
|
|
297
|
-
/>
|
|
298
|
-
</article>
|
|
268
|
+
{{ item.fork.riskNotes }}
|
|
269
|
+
</span>
|
|
270
|
+
</template>
|
|
271
|
+
<UTextarea
|
|
272
|
+
v-else
|
|
273
|
+
v-model="customText"
|
|
274
|
+
data-testid="fork-custom-input"
|
|
275
|
+
:rows="3"
|
|
276
|
+
size="xs"
|
|
277
|
+
class="mt-2 w-full"
|
|
278
|
+
:ui="{ base: 'resize-y' }"
|
|
279
|
+
:placeholder="t('forkDecision.custom.placeholder')"
|
|
280
|
+
@focus="selected = 'custom'"
|
|
281
|
+
/>
|
|
282
|
+
</template>
|
|
283
|
+
</URadioGroup>
|
|
299
284
|
|
|
300
285
|
<!-- Optional steering note -->
|
|
301
286
|
<div>
|
|
302
|
-
<
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
287
|
+
<UFormField size="xs" :label="t('forkDecision.noteLabel')">
|
|
288
|
+
<UInput
|
|
289
|
+
v-model="note"
|
|
290
|
+
size="xs"
|
|
291
|
+
class="w-full"
|
|
292
|
+
:placeholder="t('forkDecision.notePlaceholder')"
|
|
293
|
+
/>
|
|
294
|
+
</UFormField>
|
|
309
295
|
</div>
|
|
310
296
|
|
|
311
297
|
<!-- Grounded chat: ask about the forks before deciding. -->
|
|
312
298
|
<section class="rounded-xl border border-default bg-default/40 px-4 py-3">
|
|
313
|
-
<p class="text-
|
|
299
|
+
<p class="text-2xs font-medium text-muted">
|
|
314
300
|
{{ t('forkDecision.chat.title') }}
|
|
315
301
|
</p>
|
|
316
302
|
<div v-if="chat.length || answering" class="mt-2 max-h-64 space-y-2 overflow-y-auto pr-1">
|
|
@@ -322,7 +308,7 @@ const { requestClose } = useUnsavedGuard({
|
|
|
322
308
|
:class="msg.role === 'human' ? 'justify-end' : 'justify-start'"
|
|
323
309
|
>
|
|
324
310
|
<p
|
|
325
|
-
class="max-w-[85%] whitespace-pre-wrap rounded-lg px-3 py-1.5 text-
|
|
311
|
+
class="max-w-[85%] whitespace-pre-wrap rounded-lg px-3 py-1.5 text-xs"
|
|
326
312
|
:class="
|
|
327
313
|
msg.role === 'human'
|
|
328
314
|
? 'bg-app-secondary-500/15 text-app-secondary-100'
|
|
@@ -334,29 +320,31 @@ const { requestClose } = useUnsavedGuard({
|
|
|
334
320
|
</div>
|
|
335
321
|
<div v-if="answering" class="flex justify-start">
|
|
336
322
|
<p
|
|
337
|
-
class="flex items-center gap-1.5 rounded-lg bg-elevated/70 px-3 py-1.5 text-
|
|
323
|
+
class="flex items-center gap-1.5 rounded-lg bg-elevated/70 px-3 py-1.5 text-xs text-muted"
|
|
338
324
|
>
|
|
339
325
|
<UIcon name="i-lucide-loader-circle" class="h-3.5 w-3.5 animate-spin" />
|
|
340
326
|
{{ t('forkDecision.chat.thinking') }}
|
|
341
327
|
</p>
|
|
342
328
|
</div>
|
|
343
329
|
</div>
|
|
344
|
-
<p v-else class="mt-1 text-
|
|
330
|
+
<p v-else class="mt-1 text-2xs text-dimmed">
|
|
345
331
|
{{ t('forkDecision.chat.hint') }}
|
|
346
332
|
</p>
|
|
347
333
|
<div class="mt-2 flex items-end gap-2">
|
|
348
|
-
<
|
|
334
|
+
<UTextarea
|
|
349
335
|
v-model="chatInput"
|
|
350
336
|
data-testid="fork-chat-input"
|
|
351
|
-
rows="2"
|
|
337
|
+
:rows="2"
|
|
352
338
|
:disabled="!canChat"
|
|
353
339
|
:placeholder="
|
|
354
340
|
chatBudgetSpent
|
|
355
341
|
? t('forkDecision.chat.budgetSpent')
|
|
356
342
|
: t('forkDecision.chat.placeholder')
|
|
357
343
|
"
|
|
358
|
-
class="min-h-0 flex-1 resize-y rounded-md border border-muted bg-app-950/60 px-2.5 py-1.5 text-[12px] text-app-100 placeholder:text-app-600 focus:border-app-secondary-500 focus:outline-none disabled:opacity-50"
|
|
359
344
|
@keydown.enter.exact.prevent="onSend"
|
|
345
|
+
size="xs"
|
|
346
|
+
class="min-h-0 flex-1"
|
|
347
|
+
:ui="{ base: 'resize-y' }"
|
|
360
348
|
/>
|
|
361
349
|
<UButton
|
|
362
350
|
data-testid="fork-chat-send"
|
|
@@ -25,7 +25,7 @@ const { t, n } = useI18n()
|
|
|
25
25
|
|
|
26
26
|
<template>
|
|
27
27
|
<div v-if="contracts.length" class="mt-1 flex flex-col gap-1">
|
|
28
|
-
<div v-for="c in contracts" :key="c.contractId" class="text-
|
|
28
|
+
<div v-for="c in contracts" :key="c.contractId" class="text-2xs text-dimmed">
|
|
29
29
|
<span class="text-muted">{{ c.title }}</span>
|
|
30
30
|
<span class="ms-1">({{ formatLabel[c.format] }}, {{ n(c.size) }})</span>
|
|
31
31
|
<span v-if="c.operations.length" class="ms-1 font-mono text-dimmed">
|
|
@@ -42,7 +42,7 @@ const { t, n } = useI18n()
|
|
|
42
42
|
</span>
|
|
43
43
|
</div>
|
|
44
44
|
</div>
|
|
45
|
-
<p v-else class="mt-1 text-
|
|
45
|
+
<p v-else class="mt-1 text-2xs text-app-warning-500/80">
|
|
46
46
|
{{ t('foundational.contracts.none') }}
|
|
47
47
|
</p>
|
|
48
48
|
</template>
|
|
@@ -19,6 +19,7 @@ import { useBusyRows } from '~/composables/useBusyRows'
|
|
|
19
19
|
import type { ApiContractFormat, FoundationalServiceTier } from '~/types/domain'
|
|
20
20
|
import { useFoundationalServicesStore } from '~/stores/foundationalServices'
|
|
21
21
|
import FoundationalContractSummary from '~/components/foundational/FoundationalContractSummary.vue'
|
|
22
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
22
23
|
|
|
23
24
|
const catalog = useFoundationalServicesStore()
|
|
24
25
|
const toast = useToast()
|
|
@@ -92,7 +93,7 @@ async function suppress(serviceId: string) {
|
|
|
92
93
|
<div class="min-w-0 flex-1">
|
|
93
94
|
<p class="truncate text-sm font-medium text-app-100">
|
|
94
95
|
{{ s.name }}
|
|
95
|
-
<code class="ms-1 text-
|
|
96
|
+
<code class="ms-1 text-2xs text-dimmed">{{ s.id }}</code>
|
|
96
97
|
</p>
|
|
97
98
|
<p class="text-xs text-muted">{{ s.summary }}</p>
|
|
98
99
|
<div v-if="s.capabilities.length" class="mt-1 flex flex-wrap gap-1">
|
|
@@ -124,11 +125,11 @@ async function suppress(serviceId: string) {
|
|
|
124
125
|
:key="doc.contractId"
|
|
125
126
|
class="rounded-md border border-default bg-app-950/60 p-2"
|
|
126
127
|
>
|
|
127
|
-
<p class="mb-1 text-
|
|
128
|
+
<p class="mb-1 text-2xs text-muted">
|
|
128
129
|
{{ doc.title }}
|
|
129
130
|
<span v-if="doc.path" class="ms-1 font-mono text-app-600">{{ doc.path }}</span>
|
|
130
131
|
</p>
|
|
131
|
-
<pre class="max-h-64 overflow-auto text-
|
|
132
|
+
<pre class="max-h-64 overflow-auto text-2xs text-toned">{{ doc.body }}</pre>
|
|
132
133
|
</div>
|
|
133
134
|
</div>
|
|
134
135
|
</div>
|
|
@@ -139,13 +140,13 @@ async function suppress(serviceId: string) {
|
|
|
139
140
|
<!-- Only an INHERITED entry can be suppressed — an account service or one the
|
|
140
141
|
deployment registered in code; the board's own row is managed in the registry tab,
|
|
141
142
|
where deleting it is the honest action. -->
|
|
142
|
-
<
|
|
143
|
+
<IconButton
|
|
143
144
|
v-if="s.tier !== 'workspace'"
|
|
144
145
|
icon="i-lucide-eye-off"
|
|
145
146
|
size="xs"
|
|
146
147
|
variant="ghost"
|
|
147
148
|
:loading="rowBusy(`suppress:${s.id}`)"
|
|
148
|
-
:
|
|
149
|
+
:label="t('foundational.catalog.suppress')"
|
|
149
150
|
:data-testid="`foundational-suppress-${s.id}`"
|
|
150
151
|
@click="suppress(s.id)"
|
|
151
152
|
/>
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
useFoundationalServicesStore,
|
|
21
21
|
} from '~/stores/foundationalServices'
|
|
22
22
|
import FoundationalContractSummary from '~/components/foundational/FoundationalContractSummary.vue'
|
|
23
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
23
24
|
|
|
24
25
|
const props = defineProps<{ kind: FoundationalServiceOwnerKind; ownerId: string }>()
|
|
25
26
|
|
|
@@ -189,7 +190,7 @@ async function remove(service: FoundationalService) {
|
|
|
189
190
|
<div class="min-w-0 flex-1">
|
|
190
191
|
<p class="truncate text-sm font-medium text-app-100">
|
|
191
192
|
{{ s.name }}
|
|
192
|
-
<code class="ms-1 text-
|
|
193
|
+
<code class="ms-1 text-2xs text-dimmed">{{ s.id }}</code>
|
|
193
194
|
</p>
|
|
194
195
|
<p class="text-xs text-muted">{{ s.summary }}</p>
|
|
195
196
|
<div v-if="s.capabilities.length" class="mt-1 flex flex-wrap gap-1">
|
|
@@ -198,25 +199,25 @@ async function remove(service: FoundationalService) {
|
|
|
198
199
|
</UBadge>
|
|
199
200
|
</div>
|
|
200
201
|
<FoundationalContractSummary :contracts="s.contracts" :format-label="formatLabel" />
|
|
201
|
-
<p v-if="s.sourceId" class="mt-1 text-
|
|
202
|
+
<p v-if="s.sourceId" class="mt-1 text-2xs text-dimmed">
|
|
202
203
|
{{ t('foundational.registry.fromSource', { path: s.sourcePath ?? '' }) }}
|
|
203
204
|
</p>
|
|
204
205
|
</div>
|
|
205
206
|
<div class="flex shrink-0 gap-1">
|
|
206
|
-
<
|
|
207
|
+
<IconButton
|
|
207
208
|
v-if="!s.sourceId"
|
|
208
209
|
icon="i-lucide-pencil"
|
|
209
210
|
size="xs"
|
|
210
211
|
variant="ghost"
|
|
211
|
-
:
|
|
212
|
+
:label="t('foundational.registry.edit')"
|
|
212
213
|
@click="openEdit(s)"
|
|
213
214
|
/>
|
|
214
|
-
<
|
|
215
|
+
<IconButton
|
|
215
216
|
icon="i-lucide-trash-2"
|
|
216
217
|
size="xs"
|
|
217
218
|
color="error"
|
|
218
219
|
variant="ghost"
|
|
219
|
-
:
|
|
220
|
+
:label="t('foundational.registry.delete')"
|
|
220
221
|
@click="remove(s)"
|
|
221
222
|
/>
|
|
222
223
|
</div>
|
|
@@ -274,7 +275,7 @@ async function remove(service: FoundationalService) {
|
|
|
274
275
|
<p class="text-xs font-medium text-toned">
|
|
275
276
|
{{ t('foundational.registry.contractsTitle') }}
|
|
276
277
|
</p>
|
|
277
|
-
<p class="mb-2 text-
|
|
278
|
+
<p class="mb-2 text-2xs text-dimmed">
|
|
278
279
|
{{
|
|
279
280
|
draft.contractsTouched
|
|
280
281
|
? t('foundational.registry.contractsReplace')
|
|
@@ -289,12 +290,12 @@ async function remove(service: FoundationalService) {
|
|
|
289
290
|
class="flex-1"
|
|
290
291
|
/>
|
|
291
292
|
<USelect v-model="c.format" :items="formatItems" class="w-56" />
|
|
292
|
-
<
|
|
293
|
+
<IconButton
|
|
293
294
|
icon="i-lucide-x"
|
|
294
295
|
size="xs"
|
|
295
296
|
color="error"
|
|
296
297
|
variant="ghost"
|
|
297
|
-
:
|
|
298
|
+
:label="t('foundational.registry.removeContract')"
|
|
298
299
|
@click="removeContract(i)"
|
|
299
300
|
/>
|
|
300
301
|
</div>
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
} from '~/stores/foundationalServices'
|
|
28
28
|
import GitHubRepoSearchSelect from '~/components/github/GitHubRepoSearchSelect.vue'
|
|
29
29
|
import RepoTreeBrowser from '~/components/github/RepoTreeBrowser.vue'
|
|
30
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
30
31
|
|
|
31
32
|
const props = defineProps<{ kind: FoundationalServiceOwnerKind; ownerId: string }>()
|
|
32
33
|
|
|
@@ -295,29 +296,29 @@ async function unlink(id: string) {
|
|
|
295
296
|
{{ t('foundational.sources.changes') }}
|
|
296
297
|
</UBadge>
|
|
297
298
|
<div class="ms-auto flex gap-1">
|
|
298
|
-
<
|
|
299
|
+
<IconButton
|
|
299
300
|
icon="i-lucide-search-check"
|
|
300
301
|
size="xs"
|
|
301
302
|
variant="ghost"
|
|
302
303
|
:loading="rowBusy(`check:${s.id}`)"
|
|
303
|
-
:
|
|
304
|
+
:label="t('foundational.sources.check')"
|
|
304
305
|
@click="check(s.id)"
|
|
305
306
|
/>
|
|
306
|
-
<
|
|
307
|
+
<IconButton
|
|
307
308
|
icon="i-lucide-refresh-cw"
|
|
308
309
|
size="xs"
|
|
309
310
|
variant="ghost"
|
|
310
311
|
:loading="rowBusy(`sync:${s.id}`)"
|
|
311
|
-
:
|
|
312
|
+
:label="t('foundational.sources.sync')"
|
|
312
313
|
@click="sync(s.id)"
|
|
313
314
|
/>
|
|
314
|
-
<
|
|
315
|
+
<IconButton
|
|
315
316
|
icon="i-lucide-unplug"
|
|
316
317
|
size="xs"
|
|
317
318
|
color="error"
|
|
318
319
|
variant="ghost"
|
|
319
320
|
:loading="rowBusy(`unlink:${s.id}`)"
|
|
320
|
-
:
|
|
321
|
+
:label="t('foundational.sources.unlink')"
|
|
321
322
|
@click="unlink(s.id)"
|
|
322
323
|
/>
|
|
323
324
|
</div>
|
|
@@ -73,10 +73,10 @@ async function restore(serviceId: string) {
|
|
|
73
73
|
<div class="min-w-0 flex-1">
|
|
74
74
|
<p class="truncate text-sm text-toned">
|
|
75
75
|
{{ s.name || s.id }}
|
|
76
|
-
<code v-if="s.name" class="ms-1 text-
|
|
76
|
+
<code v-if="s.name" class="ms-1 text-2xs text-dimmed">{{ s.id }}</code>
|
|
77
77
|
</p>
|
|
78
78
|
<p v-if="s.summary" class="text-xs text-dimmed">{{ s.summary }}</p>
|
|
79
|
-
<p v-if="!s.inherited" class="text-
|
|
79
|
+
<p v-if="!s.inherited" class="text-2xs text-dimmed">
|
|
80
80
|
{{ t('foundational.suppressions.shadowsNothing') }}
|
|
81
81
|
</p>
|
|
82
82
|
</div>
|
|
@@ -19,6 +19,7 @@ import { showOverrideField } from '~/utils/uiMode'
|
|
|
19
19
|
import GitHubRepoSearchSelect from '~/components/github/GitHubRepoSearchSelect.vue'
|
|
20
20
|
import RepoTreeBrowser from '~/components/github/RepoTreeBrowser.vue'
|
|
21
21
|
import GitHubDocUrlImport from '~/components/fragments/GitHubDocUrlImport.vue'
|
|
22
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
22
23
|
|
|
23
24
|
const props = withDefaults(
|
|
24
25
|
defineProps<{
|
|
@@ -654,7 +655,7 @@ async function unlinkSource(id: string) {
|
|
|
654
655
|
>
|
|
655
656
|
{{ t('fragments.catalog.live', { source: f.documentRef.source }) }}
|
|
656
657
|
</UBadge>
|
|
657
|
-
<span class="ms-auto font-mono text-
|
|
658
|
+
<span class="ms-auto font-mono text-2xs text-dimmed">{{ f.id }}</span>
|
|
658
659
|
</div>
|
|
659
660
|
<p class="mt-1 text-sm text-muted">{{ f.summary }}</p>
|
|
660
661
|
<div v-if="f.tags?.length" class="mt-1 flex flex-wrap gap-1">
|
|
@@ -750,12 +751,12 @@ async function unlinkSource(id: string) {
|
|
|
750
751
|
<div class="ms-auto flex gap-1">
|
|
751
752
|
<!-- Editing a repo-SOURCED fragment locally would be overwritten on the next sync,
|
|
752
753
|
so only hand-authored fragments are editable here. -->
|
|
753
|
-
<
|
|
754
|
+
<IconButton
|
|
754
755
|
v-if="!f.source"
|
|
755
756
|
icon="i-lucide-pencil"
|
|
756
757
|
size="xs"
|
|
757
758
|
variant="ghost"
|
|
758
|
-
:
|
|
759
|
+
:label="t('common.edit')"
|
|
759
760
|
@click="startEdit(f)"
|
|
760
761
|
/>
|
|
761
762
|
<UButton
|
|
@@ -859,19 +860,19 @@ async function unlinkSource(id: string) {
|
|
|
859
860
|
</UBadge>
|
|
860
861
|
</div>
|
|
861
862
|
<p class="text-sm text-muted">{{ f.summary }}</p>
|
|
862
|
-
<p v-if="f.resolvedAt" class="text-
|
|
863
|
+
<p v-if="f.resolvedAt" class="text-2xs text-dimmed">
|
|
863
864
|
{{
|
|
864
865
|
t('fragments.documents.lastResolved', { date: d(new Date(f.resolvedAt), 'long') })
|
|
865
866
|
}}
|
|
866
867
|
</p>
|
|
867
868
|
</div>
|
|
868
869
|
<div class="ms-auto flex gap-1">
|
|
869
|
-
<
|
|
870
|
+
<IconButton
|
|
870
871
|
icon="i-lucide-refresh-cw"
|
|
871
872
|
size="xs"
|
|
872
873
|
variant="ghost"
|
|
873
874
|
:loading="rowBusy(`refresh:${f.id}`)"
|
|
874
|
-
:
|
|
875
|
+
:label="t('fragments.documents.refreshTitle')"
|
|
875
876
|
@click="refreshFragment(f.id)"
|
|
876
877
|
/>
|
|
877
878
|
<UButton
|
|
@@ -942,7 +943,7 @@ async function unlinkSource(id: string) {
|
|
|
942
943
|
<div
|
|
943
944
|
v-for="staged in stagedDocRefs"
|
|
944
945
|
:key="staged.path"
|
|
945
|
-
class="flex items-center gap-1.5 rounded bg-elevated/60 px-2 py-1 text-xs text-toned"
|
|
946
|
+
class="flex items-center gap-1.5 rounded-sm bg-elevated/60 px-2 py-1 text-xs text-toned"
|
|
946
947
|
>
|
|
947
948
|
<UIcon name="i-lucide-file-code-2" class="h-3.5 w-3.5 shrink-0 text-primary" />
|
|
948
949
|
<span class="truncate">{{ staged.path }}</span>
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
// (labelled by their raw id) so they stay visible and removable.
|
|
11
11
|
import type { PromptFragment } from '~/types/domain'
|
|
12
12
|
import { buildFragmentCategoryGroups } from '~/utils/fragmentPicker'
|
|
13
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
13
14
|
|
|
14
15
|
const props = withDefaults(
|
|
15
16
|
defineProps<{
|
|
@@ -76,9 +77,9 @@ function manageAccount() {
|
|
|
76
77
|
<template>
|
|
77
78
|
<div>
|
|
78
79
|
<div class="mb-1 flex items-center justify-between gap-2">
|
|
79
|
-
<
|
|
80
|
+
<SectionLabel v-if="label" as="span">
|
|
80
81
|
{{ label }}
|
|
81
|
-
</
|
|
82
|
+
</SectionLabel>
|
|
82
83
|
<span v-else />
|
|
83
84
|
<UPopover v-model:open="open" :content="{ align: 'end' }">
|
|
84
85
|
<UButton
|
|
@@ -98,16 +99,15 @@ function manageAccount() {
|
|
|
98
99
|
<div class="min-h-0 flex-1 overflow-y-auto p-1">
|
|
99
100
|
<template v-if="categoryGroups.length">
|
|
100
101
|
<div v-for="group in categoryGroups" :key="group.category">
|
|
101
|
-
<p
|
|
102
|
-
class="px-2 pb-0.5 pt-1.5 text-[11px] font-semibold uppercase tracking-wide text-dimmed"
|
|
103
|
-
>
|
|
102
|
+
<SectionLabel as="p" class="px-2 pb-0.5 pt-1.5">
|
|
104
103
|
{{ group.category }}
|
|
105
|
-
</
|
|
106
|
-
<
|
|
104
|
+
</SectionLabel>
|
|
105
|
+
<UButton
|
|
106
|
+
color="neutral"
|
|
107
|
+
variant="ghost"
|
|
107
108
|
v-for="f in group.fragments"
|
|
108
109
|
:key="f.id"
|
|
109
|
-
|
|
110
|
-
class="flex w-full items-center gap-2 rounded px-2 py-1.5 text-start text-sm hover:bg-elevated/60"
|
|
110
|
+
class="flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-start text-sm hover:bg-elevated/60"
|
|
111
111
|
:class="selectedSet.has(f.id) ? 'text-app-100' : 'text-toned'"
|
|
112
112
|
:title="f.summary"
|
|
113
113
|
:data-testid="`fragment-option-${f.id}`"
|
|
@@ -120,31 +120,33 @@ function manageAccount() {
|
|
|
120
120
|
:class="selectedSet.has(f.id) ? 'text-primary' : 'text-dimmed'"
|
|
121
121
|
/>
|
|
122
122
|
<span class="flex-1 truncate">{{ f.title }}</span>
|
|
123
|
-
</
|
|
123
|
+
</UButton>
|
|
124
124
|
</div>
|
|
125
125
|
</template>
|
|
126
|
-
<p v-else class="px-2 py-3 text-
|
|
126
|
+
<p v-else class="px-2 py-3 text-xs text-dimmed">
|
|
127
127
|
{{ t('inspector.fragments.pickerEmpty') }}
|
|
128
128
|
</p>
|
|
129
129
|
|
|
130
130
|
<div class="mt-1 border-t border-default pt-1">
|
|
131
|
-
<
|
|
132
|
-
|
|
133
|
-
|
|
131
|
+
<UButton
|
|
132
|
+
color="neutral"
|
|
133
|
+
variant="ghost"
|
|
134
|
+
class="flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-start text-sm text-toned hover:bg-elevated/60"
|
|
134
135
|
@click="manageBoard"
|
|
135
136
|
>
|
|
136
137
|
<UIcon name="i-lucide-book-marked" class="h-4 w-4 shrink-0 text-muted" />
|
|
137
138
|
<span class="flex-1 truncate">{{ t('inspector.fragments.manageBoard') }}</span>
|
|
138
|
-
</
|
|
139
|
-
<
|
|
139
|
+
</UButton>
|
|
140
|
+
<UButton
|
|
141
|
+
color="neutral"
|
|
142
|
+
variant="ghost"
|
|
140
143
|
v-if="accounts.enabled"
|
|
141
|
-
|
|
142
|
-
class="flex w-full items-center gap-2 rounded px-2 py-1.5 text-start text-sm text-toned hover:bg-elevated/60"
|
|
144
|
+
class="flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-start text-sm text-toned hover:bg-elevated/60"
|
|
143
145
|
@click="manageAccount"
|
|
144
146
|
>
|
|
145
147
|
<UIcon name="i-lucide-users" class="h-4 w-4 shrink-0 text-muted" />
|
|
146
148
|
<span class="flex-1 truncate">{{ t('inspector.fragments.manageAccount') }}</span>
|
|
147
|
-
</
|
|
149
|
+
</UButton>
|
|
148
150
|
</div>
|
|
149
151
|
</div>
|
|
150
152
|
|
|
@@ -178,7 +180,7 @@ function manageAccount() {
|
|
|
178
180
|
{{ f.title }}<UIcon name="i-lucide-x" class="ms-0.5 h-3 w-3" />
|
|
179
181
|
</UBadge>
|
|
180
182
|
</div>
|
|
181
|
-
<div v-else-if="emptyText" class="text-
|
|
183
|
+
<div v-else-if="emptyText" class="text-2xs text-dimmed">
|
|
182
184
|
{{ emptyText }}
|
|
183
185
|
</div>
|
|
184
186
|
</div>
|