@cat-factory/app 0.311.2 → 0.312.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 +92 -4
- package/app/app.config.ts +7 -0
- package/app/components/assistant/AssistantModal.vue +2 -5
- package/app/components/auth/AuthGate.vue +2 -1
- package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +14 -15
- package/app/components/binaryOutput/StoredAssetView.vue +1 -3
- package/app/components/board/AddTaskModal.vue +3 -10
- package/app/components/board/AgentFailureCard.vue +4 -5
- package/app/components/board/AgentStopButton.vue +5 -7
- package/app/components/board/BoardCanvas.vue +31 -30
- package/app/components/board/CreateInitiativeModal.vue +2 -4
- package/app/components/board/RecurringPipelineModal.vue +2 -7
- package/app/components/board/nodes/AgentChip.vue +3 -2
- package/app/components/board/nodes/BlockNode.vue +14 -11
- package/app/components/board/nodes/InitiativeCard.vue +6 -3
- package/app/components/board/nodes/TaskCard.vue +45 -212
- package/app/components/bootstrap/AdoptionReviewModal.vue +2 -5
- package/app/components/bootstrap/BootstrapModal.vue +6 -15
- package/app/components/bootstrap/BootstrapRunSteps.vue +3 -1
- package/app/components/brainstorm/BrainstormWindow.vue +32 -26
- package/app/components/bugFishing/BugFishingWindow.vue +15 -13
- package/app/components/clarity/ClarityReviewWindow.vue +31 -26
- package/app/components/common/ClarificationItem.vue +3 -1
- package/app/components/common/EmptyState.vue +41 -19
- package/app/components/common/InterviewGateNotice.vue +3 -1
- package/app/components/common/Spinner.vue +28 -0
- package/app/components/consensus/ConsensusSessionWindow.vue +5 -5
- package/app/components/docs/DocInterviewWindow.vue +6 -6
- package/app/components/documents/ContextDocumentPicker.vue +2 -2
- package/app/components/documents/DocumentImportModal.vue +9 -8
- package/app/components/documents/DocumentSourceConnectModal.vue +10 -10
- package/app/components/documents/DocumentTemplatesModal.vue +13 -7
- package/app/components/documents/RepoContextDocPicker.vue +2 -2
- package/app/components/documents/SpawnPreviewModal.vue +4 -6
- package/app/components/documents/StartFromDesignModal.vue +2 -1
- package/app/components/documents/TaskContextDocs.vue +4 -5
- package/app/components/environments/EnvironmentStatusPanel.vue +11 -8
- package/app/components/environments/steps/EnvPickStep.vue +7 -3
- package/app/components/environments/steps/EnvPreflightStep.vue +6 -5
- package/app/components/focus/BlockFocusView.vue +6 -5
- package/app/components/followUp/FollowUpWindow.vue +7 -9
- package/app/components/forkDecision/ForkDecisionWindow.vue +9 -8
- package/app/components/foundational/FoundationalServiceCatalogList.vue +9 -5
- package/app/components/foundational/FoundationalServiceRegistry.vue +11 -7
- package/app/components/foundational/FoundationalServiceSources.vue +20 -22
- package/app/components/foundational/FoundationalSuppressions.vue +2 -2
- package/app/components/foundational/ServiceCatalogConnection.vue +15 -15
- package/app/components/fragments/FragmentLibraryManager.vue +36 -34
- package/app/components/fragments/FragmentSelector.vue +7 -3
- package/app/components/gates/GateResultView.vue +6 -9
- package/app/components/github/AddServiceFromRepoModal.vue +6 -10
- package/app/components/github/GitHubConnect.vue +10 -17
- package/app/components/github/GitHubPanel.vue +44 -47
- package/app/components/github/RepoTreeBrowser.vue +9 -5
- package/app/components/guidedReview/GuidedReviewModal.vue +16 -6
- package/app/components/guidedReview/GuidedReviewOverview.vue +2 -1
- package/app/components/guidedReview/GuidedReviewPicker.vue +10 -7
- package/app/components/guidedReview/GuidedReviewThread.vue +9 -4
- package/app/components/humanTest/HumanTestWindow.vue +2 -1
- package/app/components/initiative/InitiativePlanningWindow.vue +6 -6
- package/app/components/initiative/InitiativeTrackerWindow.vue +11 -11
- package/app/components/judge/JudgeResultView.vue +2 -7
- package/app/components/kaizen/KaizenPanel.vue +20 -5
- package/app/components/kaizen/KaizenStepStatus.vue +2 -1
- package/app/components/layout/AccountAuditLog.vue +11 -3
- package/app/components/layout/AccountDeploymentSettings.vue +17 -62
- package/app/components/layout/AccountFailureKindRules.vue +6 -5
- package/app/components/layout/AccountModelPolicySettings.vue +2 -6
- package/app/components/layout/AccountPlatformAlertSettings.vue +5 -13
- package/app/components/layout/AccountRiskPolicySettings.vue +13 -14
- package/app/components/layout/AccountRunCredentialSettings.vue +2 -2
- package/app/components/layout/AccountTeamSettings.vue +12 -9
- package/app/components/layout/BoardSwitcher.vue +2 -2
- package/app/components/layout/BoardToolbar.vue +27 -37
- package/app/components/layout/BoardTopOverlays.vue +8 -2
- package/app/components/layout/CommandBar.vue +7 -3
- package/app/components/layout/ConnectionStatusBanner.vue +2 -1
- package/app/components/layout/IntegrationsHub.vue +7 -3
- package/app/components/layout/ModelProvidersHub.vue +7 -3
- package/app/components/layout/NotificationsInbox.vue +3 -11
- package/app/components/layout/SideBar.vue +5 -0
- package/app/components/layout/WorkViewSwitcher.vue +64 -0
- package/app/components/layout/WorkspaceMembersSettings.vue +12 -5
- package/app/components/media/ArtifactLightbox.vue +4 -3
- package/app/components/notifications/NotificationSettingsPanel.vue +4 -11
- package/app/components/observability/ToolCallList.vue +12 -17
- package/app/components/panels/AgentStepDetail.vue +5 -5
- package/app/components/panels/GenericStructuredResultView.vue +6 -9
- package/app/components/panels/InspectorPanel.vue +2 -1
- package/app/components/panels/MergerResultView.vue +5 -6
- package/app/components/panels/ObservabilityPanel.vue +26 -41
- package/app/components/panels/OperatorDashboardPanel.vue +29 -17
- package/app/components/panels/ReportsPanel.vue +17 -11
- package/app/components/panels/ReportsSpendBreakdown.vue +7 -3
- package/app/components/panels/RunDetailLoadState.vue +4 -3
- package/app/components/panels/StepContainerStatus.vue +4 -3
- package/app/components/panels/StepDelegatedStatus.vue +3 -2
- package/app/components/panels/StepMetadataCard.vue +6 -8
- package/app/components/panels/StepRunMeta.vue +2 -5
- package/app/components/panels/inspector/ContainerSummary.vue +7 -1
- package/app/components/panels/inspector/EpicChildren.vue +7 -3
- package/app/components/panels/inspector/FrontendConfig.vue +7 -3
- package/app/components/panels/inspector/InitiativeInspector.vue +5 -2
- package/app/components/panels/inspector/ServiceConnections.vue +7 -3
- package/app/components/panels/inspector/ServiceReleaseHealthConfig.vue +2 -6
- package/app/components/panels/inspector/ServiceTestSecrets.vue +2 -6
- package/app/components/panels/inspector/ServiceTestingContext.vue +2 -6
- package/app/components/panels/inspector/ServiceValidationConfig.vue +38 -39
- package/app/components/panels/inspector/TaskExecution.vue +5 -6
- package/app/components/panels/inspector/TaskRunSettings.vue +7 -3
- package/app/components/panels/inspector/TaskStructure.vue +0 -1
- package/app/components/pipeline/AgentPromptEditor.vue +25 -18
- package/app/components/pipeline/PipelineBuilder.vue +14 -24
- package/app/components/pipeline/PipelineProgress.vue +16 -17
- package/app/components/prReview/PrReviewPhaseBadge.vue +3 -2
- package/app/components/prReview/PrReviewWindow.vue +16 -20
- package/app/components/providers/ApiKeysSection.vue +2 -6
- package/app/components/providers/PersonalCredentialModal.vue +2 -6
- package/app/components/providers/PersonalSubscriptionSection.vue +3 -7
- package/app/components/providers/VendorCredentialsModal.vue +2 -6
- package/app/components/provisioning/ProvisioningLogsDrawer.vue +10 -6
- package/app/components/queue/QueueCard.vue +269 -0
- package/app/components/queue/QueueView.vue +192 -0
- package/app/components/ralph/RalphLoopResultView.vue +2 -7
- package/app/components/requirements/RequirementsReviewWindow.vue +44 -39
- package/app/components/sandbox/SandboxPanel.vue +37 -25
- package/app/components/settings/AccountSettingsPanel.vue +6 -3
- package/app/components/settings/ApiTokensPanel.vue +2 -6
- package/app/components/settings/BudgetSettings.vue +2 -2
- package/app/components/settings/CapabilityCredentialsPanel.vue +2 -6
- package/app/components/settings/CloudflareHandlerSection.vue +3 -7
- package/app/components/settings/ConsensusGroupsSection.vue +7 -3
- package/app/components/settings/CustomManifestTypeEditor.vue +7 -3
- package/app/components/settings/DefaultProvisionTypeSection.vue +2 -2
- package/app/components/settings/InfraHandlersConfigurator.vue +8 -11
- package/app/components/settings/IssueTrackerPanel.vue +9 -9
- package/app/components/settings/LocalContainerPoolSettings.vue +2 -6
- package/app/components/settings/LocalModelEndpointsPanel.vue +5 -7
- package/app/components/settings/McpAuthorizeScreen.vue +8 -3
- package/app/components/settings/McpOAuthCallbackScreen.vue +2 -1
- package/app/components/settings/ModelConfigurationPanel.vue +45 -17
- package/app/components/settings/ObservabilityConnectionPanel.vue +4 -15
- package/app/components/settings/OpenRouterCatalogPanel.vue +8 -24
- package/app/components/settings/PackageRegistriesPanel.vue +2 -6
- package/app/components/settings/ProviderConnectionTab.vue +3 -7
- package/app/components/settings/RiskPolicyPanel.vue +4 -16
- package/app/components/settings/SharedStacksPanel.vue +8 -18
- package/app/components/settings/TaskTypeSuppressionsPanel.vue +10 -6
- package/app/components/settings/UsageSettings.vue +11 -2
- package/app/components/settings/UserSecretsSection.vue +5 -7
- package/app/components/settings/WorkspaceMetadataSettings.vue +9 -9
- package/app/components/settings/WorkspaceSettingsPanel.vue +3 -11
- package/app/components/skills/ReviewSkillQueue.vue +7 -3
- package/app/components/skills/SkillLibraryManager.vue +20 -18
- package/app/components/slack/SlackPanel.vue +5 -8
- package/app/components/spec/ServiceSpecWindow.vue +32 -29
- package/app/components/tasks/BugHuntModal.vue +23 -19
- package/app/components/tasks/ContextIssuePicker.vue +2 -2
- package/app/components/tasks/TaskContextIssues.vue +4 -5
- package/app/components/tasks/TaskImportModal.vue +10 -8
- package/app/components/tasks/TaskSourceConnectModal.vue +11 -11
- package/app/components/testing/TestReportWindow.vue +6 -12
- package/app/components/tutorial/TutorialCatalogue.vue +7 -3
- package/app/components/tutorial/TutorialOverlay.vue +2 -1
- package/app/components/tutorial/TutorialPrompt.vue +7 -3
- package/app/components/vcs/GitLabConnect.vue +2 -6
- package/app/components/visualConfirm/VisualConfirmationWindow.vue +9 -4
- package/app/composables/toastTitleKeys.spec.ts +143 -0
- package/app/composables/useActionToast.spec.ts +71 -0
- package/app/composables/useActionToast.ts +101 -0
- package/app/composables/useBlockDeletion.ts +3 -6
- package/app/composables/useConfirmAction.ts +5 -3
- package/app/composables/useContextLinking.spec.ts +3 -0
- package/app/composables/useContextLinking.ts +11 -16
- package/app/composables/useCopyToClipboard.ts +4 -3
- package/app/composables/useFrameLanes.ts +6 -82
- package/app/composables/useNavContributions.ts +6 -5
- package/app/composables/usePipelineErrorToast.spec.ts +24 -0
- package/app/composables/usePipelineErrorToast.ts +26 -2
- package/app/composables/usePipelineLibraryActions.ts +8 -9
- package/app/composables/useTaskActions.ts +254 -0
- package/app/composables/useTaskLaneClassifier.ts +88 -0
- package/app/modular/nav-contributions.spec.ts +4 -0
- package/app/modular/nav-contributions.ts +31 -0
- package/app/modular/tutorial-tours.ts +10 -0
- package/app/pages/index.vue +42 -8
- package/app/stores/board/context.ts +4 -3
- package/app/stores/board/placement.ts +8 -20
- package/app/stores/board/removal.ts +4 -13
- package/app/stores/board.spec.ts +10 -1
- package/app/stores/board.ts +3 -2
- package/app/stores/workView.ts +51 -0
- package/app/stores/workspaceQueue.ts +148 -0
- package/app/utils/bootstrapSteps.ts +11 -2
- package/app/utils/pipelineRender.ts +21 -8
- package/app/utils/queueSections.spec.ts +111 -0
- package/app/utils/queueSections.ts +117 -0
- package/app/utils/workView.spec.ts +16 -0
- package/app/utils/workView.ts +25 -0
- package/i18n/locales/de.json +73 -32
- package/i18n/locales/en.json +73 -32
- package/i18n/locales/es.json +73 -32
- package/i18n/locales/fr.json +73 -32
- package/i18n/locales/he.json +73 -32
- package/i18n/locales/it.json +73 -32
- package/i18n/locales/ja.json +73 -32
- package/i18n/locales/pl.json +73 -32
- package/i18n/locales/tr.json +73 -32
- package/i18n/locales/uk.json +73 -32
- package/package.json +1 -1
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { computed } from 'vue'
|
|
7
7
|
import JourneyStepNav from '~/components/environments/steps/JourneyStepNav.vue'
|
|
8
8
|
import { useEnvironmentWizardTarget } from '~/modular/journeys/environmentSetup.frame'
|
|
9
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
9
10
|
|
|
10
11
|
const props = defineProps<{
|
|
11
12
|
input: { frameId: string | null }
|
|
@@ -48,13 +49,13 @@ const PREFLIGHT_COLOR: Record<'pass' | 'warn' | 'fail', 'success' | 'warning' |
|
|
|
48
49
|
</UButton>
|
|
49
50
|
</div>
|
|
50
51
|
|
|
51
|
-
<
|
|
52
|
+
<EmptyState
|
|
52
53
|
v-if="!store.recipe.prerequisites?.length"
|
|
53
|
-
|
|
54
|
+
compact
|
|
55
|
+
icon="i-lucide-list-checks"
|
|
56
|
+
:title="t('environmentWizard.preflight.none')"
|
|
54
57
|
data-testid="env-setup-preflight-none"
|
|
55
|
-
|
|
56
|
-
{{ t('environmentWizard.preflight.none') }}
|
|
57
|
-
</p>
|
|
58
|
+
/>
|
|
58
59
|
<p
|
|
59
60
|
v-else-if="preflightsUnavailable"
|
|
60
61
|
class="text-xs text-app-warning-300/80"
|
|
@@ -7,6 +7,7 @@ import PipelineProgress from '~/components/pipeline/PipelineProgress.vue'
|
|
|
7
7
|
import IconButton from '~/components/common/IconButton.vue'
|
|
8
8
|
import { useInitiativePlanning } from '~/composables/useInitiativePlanning'
|
|
9
9
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
10
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
10
11
|
|
|
11
12
|
const board = useBoardStore()
|
|
12
13
|
const pipelines = usePipelinesStore()
|
|
@@ -214,12 +215,12 @@ function openApprovalFor(approvalId: string) {
|
|
|
214
215
|
@open-approval="openApprovalFor"
|
|
215
216
|
/>
|
|
216
217
|
|
|
217
|
-
<
|
|
218
|
+
<EmptyState
|
|
218
219
|
v-else
|
|
219
|
-
class="flex
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
220
|
+
class="flex-1"
|
|
221
|
+
icon="i-lucide-workflow"
|
|
222
|
+
:title="t('focus.emptyPipelineHint')"
|
|
223
|
+
/>
|
|
223
224
|
</section>
|
|
224
225
|
|
|
225
226
|
<!-- side: details -->
|
|
@@ -13,6 +13,7 @@ import { useFollowUpsStore } from '~/stores/followUps'
|
|
|
13
13
|
import type { FollowUpItem, FollowUpResolution } from '~/types/execution'
|
|
14
14
|
import { FOLLOW_UP_COMPANION_META } from '~/utils/catalog'
|
|
15
15
|
import ResultWindowShell from '~/components/panels/ResultWindowShell.vue'
|
|
16
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
16
17
|
|
|
17
18
|
const execution = useExecutionStore()
|
|
18
19
|
const board = useBoardStore()
|
|
@@ -156,16 +157,13 @@ function hasRecordedAnswer(item: FollowUpItem): boolean {
|
|
|
156
157
|
|
|
157
158
|
<div class="min-h-0 flex-1 overflow-y-auto px-5 py-4">
|
|
158
159
|
<!-- Empty -->
|
|
159
|
-
<
|
|
160
|
+
<EmptyState
|
|
160
161
|
v-if="items.length === 0"
|
|
161
|
-
class="
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
{{ t('followUp.empty.hint') }}
|
|
167
|
-
</p>
|
|
168
|
-
</div>
|
|
162
|
+
class="h-full"
|
|
163
|
+
:icon="FOLLOW_UP_COMPANION_META.icon"
|
|
164
|
+
:title="t('followUp.empty.title')"
|
|
165
|
+
:description="t('followUp.empty.hint')"
|
|
166
|
+
/>
|
|
169
167
|
|
|
170
168
|
<div v-else class="space-y-3">
|
|
171
169
|
<p
|
|
@@ -15,6 +15,8 @@ import { useForkDecisionStore } from '~/stores/forkDecision'
|
|
|
15
15
|
import type { ForkChatMessage, ForkDecisionStepState, ForkOption } from '~/types/execution'
|
|
16
16
|
import { FORK_DECISION_META } from '~/utils/catalog'
|
|
17
17
|
import ResultWindowShell from '~/components/panels/ResultWindowShell.vue'
|
|
18
|
+
import Spinner from '~/components/common/Spinner.vue'
|
|
19
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
18
20
|
|
|
19
21
|
const execution = useExecutionStore()
|
|
20
22
|
const board = useBoardStore()
|
|
@@ -170,7 +172,7 @@ const { requestClose } = useUnsavedGuard({
|
|
|
170
172
|
v-if="status === 'proposing'"
|
|
171
173
|
class="flex h-full flex-col items-center justify-center gap-2 py-10 text-center text-muted"
|
|
172
174
|
>
|
|
173
|
-
<
|
|
175
|
+
<Spinner class="h-8 w-8 opacity-60" />
|
|
174
176
|
<p class="text-sm">{{ t('forkDecision.proposing.title') }}</p>
|
|
175
177
|
<p class="max-w-sm text-2xs text-dimmed">
|
|
176
178
|
{{ t('forkDecision.proposing.hint') }}
|
|
@@ -322,7 +324,7 @@ const { requestClose } = useUnsavedGuard({
|
|
|
322
324
|
<p
|
|
323
325
|
class="flex items-center gap-1.5 rounded-lg bg-elevated/70 px-3 py-1.5 text-xs text-muted"
|
|
324
326
|
>
|
|
325
|
-
<
|
|
327
|
+
<Spinner class="h-3.5 w-3.5" />
|
|
326
328
|
{{ t('forkDecision.chat.thinking') }}
|
|
327
329
|
</p>
|
|
328
330
|
</div>
|
|
@@ -364,13 +366,12 @@ const { requestClose } = useUnsavedGuard({
|
|
|
364
366
|
</div>
|
|
365
367
|
|
|
366
368
|
<!-- Skipped / no state: nothing to decide. -->
|
|
367
|
-
<
|
|
369
|
+
<EmptyState
|
|
368
370
|
v-else
|
|
369
|
-
class="
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
</div>
|
|
371
|
+
class="h-full"
|
|
372
|
+
:icon="FORK_DECISION_META.icon"
|
|
373
|
+
:title="t('forkDecision.empty.title')"
|
|
374
|
+
/>
|
|
374
375
|
</div>
|
|
375
376
|
|
|
376
377
|
<footer
|
|
@@ -20,9 +20,10 @@ import type { ApiContractFormat, FoundationalServiceTier } from '~/types/domain'
|
|
|
20
20
|
import { useFoundationalServicesStore } from '~/stores/foundationalServices'
|
|
21
21
|
import FoundationalContractSummary from '~/components/foundational/FoundationalContractSummary.vue'
|
|
22
22
|
import IconButton from '~/components/common/IconButton.vue'
|
|
23
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
23
24
|
|
|
24
25
|
const catalog = useFoundationalServicesStore()
|
|
25
|
-
const
|
|
26
|
+
const actionToast = useActionToast()
|
|
26
27
|
const { present } = usePipelineErrorToast()
|
|
27
28
|
const { t } = useI18n()
|
|
28
29
|
|
|
@@ -71,7 +72,7 @@ async function suppress(serviceId: string) {
|
|
|
71
72
|
await withRow(`suppress:${serviceId}`, async () => {
|
|
72
73
|
try {
|
|
73
74
|
await catalog.suppress(serviceId)
|
|
74
|
-
|
|
75
|
+
actionToast.success('foundational.toast.suppressed')
|
|
75
76
|
} catch (e) {
|
|
76
77
|
present(e, 'foundational.toast.suppressFailed')
|
|
77
78
|
}
|
|
@@ -156,8 +157,11 @@ async function suppress(serviceId: string) {
|
|
|
156
157
|
</div>
|
|
157
158
|
</div>
|
|
158
159
|
|
|
159
|
-
<
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
<EmptyState
|
|
161
|
+
v-if="!catalog.resolved.length"
|
|
162
|
+
compact
|
|
163
|
+
icon="i-lucide-package"
|
|
164
|
+
:title="t('foundational.catalog.empty')"
|
|
165
|
+
/>
|
|
162
166
|
</div>
|
|
163
167
|
</template>
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
} from '~/stores/foundationalServices'
|
|
22
22
|
import FoundationalContractSummary from '~/components/foundational/FoundationalContractSummary.vue'
|
|
23
23
|
import IconButton from '~/components/common/IconButton.vue'
|
|
24
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
24
25
|
|
|
25
26
|
const props = defineProps<{ kind: FoundationalServiceOwnerKind; ownerId: string }>()
|
|
26
27
|
|
|
@@ -28,7 +29,7 @@ const catalog =
|
|
|
28
29
|
props.kind === 'workspace'
|
|
29
30
|
? useFoundationalServicesStore()
|
|
30
31
|
: useFoundationalServices(props.kind, props.ownerId)
|
|
31
|
-
const
|
|
32
|
+
const actionToast = useActionToast()
|
|
32
33
|
const { present } = usePipelineErrorToast()
|
|
33
34
|
const { t } = useI18n()
|
|
34
35
|
const { confirm } = useConfirm()
|
|
@@ -131,7 +132,7 @@ async function save() {
|
|
|
131
132
|
capabilities: capabilityList.value,
|
|
132
133
|
...(contracts ? { contracts } : {}),
|
|
133
134
|
})
|
|
134
|
-
|
|
135
|
+
actionToast.success('foundational.toast.created')
|
|
135
136
|
} else {
|
|
136
137
|
await catalog.update(draft.id, {
|
|
137
138
|
name: draft.name.trim(),
|
|
@@ -140,7 +141,7 @@ async function save() {
|
|
|
140
141
|
capabilities: capabilityList.value,
|
|
141
142
|
...(contracts ? { contracts } : {}),
|
|
142
143
|
})
|
|
143
|
-
|
|
144
|
+
actionToast.success('foundational.toast.updated')
|
|
144
145
|
}
|
|
145
146
|
editing.value = null
|
|
146
147
|
} catch (e) {
|
|
@@ -171,7 +172,7 @@ async function remove(service: FoundationalService) {
|
|
|
171
172
|
if (!ok) return
|
|
172
173
|
try {
|
|
173
174
|
await catalog.remove(service.id)
|
|
174
|
-
|
|
175
|
+
actionToast.success('foundational.toast.deleted')
|
|
175
176
|
} catch (e) {
|
|
176
177
|
present(e, 'foundational.toast.deleteFailed')
|
|
177
178
|
}
|
|
@@ -224,9 +225,12 @@ async function remove(service: FoundationalService) {
|
|
|
224
225
|
</div>
|
|
225
226
|
</div>
|
|
226
227
|
</div>
|
|
227
|
-
<
|
|
228
|
-
|
|
229
|
-
|
|
228
|
+
<EmptyState
|
|
229
|
+
v-if="!catalog.services.length"
|
|
230
|
+
compact
|
|
231
|
+
icon="i-lucide-package"
|
|
232
|
+
:title="t('foundational.registry.empty')"
|
|
233
|
+
/>
|
|
230
234
|
|
|
231
235
|
<UButton
|
|
232
236
|
v-if="editing === null"
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
import GitHubRepoSearchSelect from '~/components/github/GitHubRepoSearchSelect.vue'
|
|
29
29
|
import RepoTreeBrowser from '~/components/github/RepoTreeBrowser.vue'
|
|
30
30
|
import IconButton from '~/components/common/IconButton.vue'
|
|
31
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
31
32
|
|
|
32
33
|
const props = defineProps<{ kind: FoundationalServiceOwnerKind; ownerId: string }>()
|
|
33
34
|
|
|
@@ -36,7 +37,7 @@ const catalog =
|
|
|
36
37
|
? useFoundationalServicesStore()
|
|
37
38
|
: useFoundationalServices(props.kind, props.ownerId)
|
|
38
39
|
const github = useGitHubStore()
|
|
39
|
-
const
|
|
40
|
+
const actionToast = useActionToast()
|
|
40
41
|
const { present } = usePipelineErrorToast()
|
|
41
42
|
const { t, d } = useI18n()
|
|
42
43
|
const { confirm } = useConfirm()
|
|
@@ -163,7 +164,7 @@ async function link() {
|
|
|
163
164
|
: {}),
|
|
164
165
|
})
|
|
165
166
|
resetDraft()
|
|
166
|
-
|
|
167
|
+
actionToast.success('foundational.toast.sourceLinked')
|
|
167
168
|
return result
|
|
168
169
|
} catch (e) {
|
|
169
170
|
present(e, 'foundational.toast.linkSourceFailed')
|
|
@@ -185,17 +186,14 @@ async function sync(id: string) {
|
|
|
185
186
|
)
|
|
186
187
|
const coverage = result.folderScan ? folderScanNotes.value[result.folderScan] : null
|
|
187
188
|
if (coverage) notes.push(coverage)
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}),
|
|
189
|
+
// A folder we could not fully see, or could not find at all, is the one sync outcome a
|
|
190
|
+
// human has to act on: the counts alone would read as an ordinary quiet success.
|
|
191
|
+
const synced = {
|
|
192
|
+
params: { updated: result.upserted, removed: result.tombstoned },
|
|
193
193
|
...(notes.length ? { description: notes.join(' ') } : {}),
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
color: coverage ? 'warning' : 'info',
|
|
198
|
-
})
|
|
194
|
+
}
|
|
195
|
+
if (coverage) actionToast.warning('foundational.toast.synced', synced)
|
|
196
|
+
else actionToast.success('foundational.toast.synced', synced)
|
|
199
197
|
} catch (e) {
|
|
200
198
|
present(e, 'foundational.toast.syncFailed')
|
|
201
199
|
}
|
|
@@ -206,12 +204,9 @@ async function check(id: string) {
|
|
|
206
204
|
await withRow(`check:${id}`, async () => {
|
|
207
205
|
try {
|
|
208
206
|
const status = await catalog.checkSource(id)
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
: t('foundational.toast.upToDate'),
|
|
213
|
-
icon: status.changed ? 'i-lucide-bell-dot' : 'i-lucide-check',
|
|
214
|
-
})
|
|
207
|
+
actionToast.info(
|
|
208
|
+
status.changed ? 'foundational.toast.changesAvailable' : 'foundational.toast.upToDate',
|
|
209
|
+
)
|
|
215
210
|
} catch (e) {
|
|
216
211
|
present(e, 'foundational.toast.checkSourceFailed')
|
|
217
212
|
}
|
|
@@ -233,7 +228,7 @@ async function unlink(id: string) {
|
|
|
233
228
|
await withRow(`unlink:${id}`, async () => {
|
|
234
229
|
try {
|
|
235
230
|
await catalog.unlinkSource(id)
|
|
236
|
-
|
|
231
|
+
actionToast.success('foundational.toast.sourceUnlinked')
|
|
237
232
|
} catch (e) {
|
|
238
233
|
present(e, 'foundational.toast.unlinkSourceFailed')
|
|
239
234
|
}
|
|
@@ -325,9 +320,12 @@ async function unlink(id: string) {
|
|
|
325
320
|
/>
|
|
326
321
|
</div>
|
|
327
322
|
</div>
|
|
328
|
-
<
|
|
329
|
-
|
|
330
|
-
|
|
323
|
+
<EmptyState
|
|
324
|
+
v-if="!catalog.sources.length"
|
|
325
|
+
compact
|
|
326
|
+
icon="i-lucide-git-branch"
|
|
327
|
+
:title="t('foundational.sources.empty')"
|
|
328
|
+
/>
|
|
331
329
|
|
|
332
330
|
<!-- Linking needs the GitHub integration; say so rather than offering a form that 503s. -->
|
|
333
331
|
<div
|
|
@@ -23,7 +23,7 @@ const catalog =
|
|
|
23
23
|
props.kind === 'workspace'
|
|
24
24
|
? useFoundationalServicesStore()
|
|
25
25
|
: useFoundationalServices(props.kind, props.ownerId)
|
|
26
|
-
const
|
|
26
|
+
const actionToast = useActionToast()
|
|
27
27
|
const { present } = usePipelineErrorToast()
|
|
28
28
|
const { t } = useI18n()
|
|
29
29
|
|
|
@@ -47,7 +47,7 @@ async function restore(serviceId: string) {
|
|
|
47
47
|
busyRows.add(serviceId)
|
|
48
48
|
try {
|
|
49
49
|
await catalog.restore(serviceId)
|
|
50
|
-
|
|
50
|
+
actionToast.success('foundational.toast.restored')
|
|
51
51
|
} catch (e) {
|
|
52
52
|
present(e, 'foundational.toast.restoreFailed')
|
|
53
53
|
} finally {
|
|
@@ -22,8 +22,8 @@ import {
|
|
|
22
22
|
} from '~/utils/serviceCatalog'
|
|
23
23
|
|
|
24
24
|
const catalog = useFoundationalServicesStore()
|
|
25
|
-
const
|
|
26
|
-
const { present } = usePipelineErrorToast()
|
|
25
|
+
const actionToast = useActionToast()
|
|
26
|
+
const { present, presentReported } = usePipelineErrorToast()
|
|
27
27
|
const { t, d } = useI18n()
|
|
28
28
|
const { confirm } = useConfirm()
|
|
29
29
|
|
|
@@ -137,7 +137,7 @@ async function connect() {
|
|
|
137
137
|
await withBusy('connect', async () => {
|
|
138
138
|
try {
|
|
139
139
|
await catalog.connectServiceCatalog(buildInput())
|
|
140
|
-
|
|
140
|
+
actionToast.success('serviceCatalog.toast.connected')
|
|
141
141
|
} catch (error) {
|
|
142
142
|
present(error, 'serviceCatalog.toast.connectFailed')
|
|
143
143
|
return
|
|
@@ -154,13 +154,13 @@ async function probe() {
|
|
|
154
154
|
await withBusy('probe', async () => {
|
|
155
155
|
try {
|
|
156
156
|
const result = await catalog.probeServiceCatalog(buildInput())
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
157
|
+
if (result.ok) {
|
|
158
|
+
// The probe's `message` is backend prose: on a failure it is detail behind the disclosure,
|
|
159
|
+
// and on a success the translated title is the whole of what the reader needs.
|
|
160
|
+
actionToast.success('serviceCatalog.toast.probeOk')
|
|
161
|
+
} else {
|
|
162
|
+
presentReported(result.message, 'serviceCatalog.toast.probeFailed')
|
|
163
|
+
}
|
|
164
164
|
} catch (error) {
|
|
165
165
|
present(error, 'serviceCatalog.toast.probeFailed')
|
|
166
166
|
}
|
|
@@ -175,15 +175,15 @@ async function importNow() {
|
|
|
175
175
|
async function runImport(): Promise<void> {
|
|
176
176
|
try {
|
|
177
177
|
const result = await catalog.importServiceCatalog()
|
|
178
|
-
|
|
179
|
-
title: t('serviceCatalog.toast.imported'),
|
|
178
|
+
const imported = {
|
|
180
179
|
description: t('serviceCatalog.toast.importedDetail', {
|
|
181
180
|
upserted: result.upserted,
|
|
182
181
|
unchanged: result.unchanged,
|
|
183
182
|
tombstoned: result.tombstoned,
|
|
184
183
|
}),
|
|
185
|
-
|
|
186
|
-
|
|
184
|
+
}
|
|
185
|
+
if (result.status === 'ok') actionToast.success('serviceCatalog.toast.imported', imported)
|
|
186
|
+
else actionToast.warning('serviceCatalog.toast.imported', imported)
|
|
187
187
|
} catch (error) {
|
|
188
188
|
present(error, 'serviceCatalog.toast.importFailed')
|
|
189
189
|
}
|
|
@@ -206,7 +206,7 @@ async function disconnect() {
|
|
|
206
206
|
await withBusy('disconnect', async () => {
|
|
207
207
|
try {
|
|
208
208
|
await catalog.disconnectServiceCatalog()
|
|
209
|
-
|
|
209
|
+
actionToast.success('serviceCatalog.toast.disconnected')
|
|
210
210
|
} catch (error) {
|
|
211
211
|
present(error, 'serviceCatalog.toast.disconnectFailed')
|
|
212
212
|
}
|
|
@@ -20,6 +20,7 @@ import GitHubRepoSearchSelect from '~/components/github/GitHubRepoSearchSelect.v
|
|
|
20
20
|
import RepoTreeBrowser from '~/components/github/RepoTreeBrowser.vue'
|
|
21
21
|
import GitHubDocUrlImport from '~/components/fragments/GitHubDocUrlImport.vue'
|
|
22
22
|
import IconButton from '~/components/common/IconButton.vue'
|
|
23
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
23
24
|
|
|
24
25
|
const props = withDefaults(
|
|
25
26
|
defineProps<{
|
|
@@ -41,7 +42,7 @@ const library =
|
|
|
41
42
|
: useFragmentLibrary(props.kind, props.ownerId)
|
|
42
43
|
const documents = useDocumentsStore()
|
|
43
44
|
const github = useGitHubStore()
|
|
44
|
-
const
|
|
45
|
+
const actionToast = useActionToast()
|
|
45
46
|
const { present } = usePipelineErrorToast()
|
|
46
47
|
const { t, d } = useI18n()
|
|
47
48
|
const { confirm } = useConfirm()
|
|
@@ -207,7 +208,7 @@ async function saveEdit() {
|
|
|
207
208
|
.filter(Boolean),
|
|
208
209
|
})
|
|
209
210
|
editDraft.value = null
|
|
210
|
-
|
|
211
|
+
actionToast.success('fragments.toast.updated')
|
|
211
212
|
} catch (e) {
|
|
212
213
|
present(e, 'fragments.toast.updateFailed')
|
|
213
214
|
}
|
|
@@ -229,7 +230,7 @@ async function createFragment() {
|
|
|
229
230
|
.filter(Boolean),
|
|
230
231
|
})
|
|
231
232
|
draft.value = { title: '', summary: '', body: '', brief: '', tags: '' }
|
|
232
|
-
|
|
233
|
+
actionToast.success('fragments.toast.added')
|
|
233
234
|
} catch (e) {
|
|
234
235
|
present(e, 'fragments.toast.addFailed')
|
|
235
236
|
} finally {
|
|
@@ -250,7 +251,7 @@ async function removeFragment(id: string) {
|
|
|
250
251
|
await withRow(`remove:${id}`, async () => {
|
|
251
252
|
try {
|
|
252
253
|
await library.remove(id)
|
|
253
|
-
|
|
254
|
+
actionToast.success('fragments.toast.removed')
|
|
254
255
|
} catch (e) {
|
|
255
256
|
present(e, 'fragments.toast.removeFailed')
|
|
256
257
|
}
|
|
@@ -415,7 +416,7 @@ async function linkDocumentFragment() {
|
|
|
415
416
|
// Free-text field: exactly one ref.
|
|
416
417
|
await library.createDocumentFragment({ source, ref: docDraft.value.ref.trim(), tags })
|
|
417
418
|
docDraft.value = { source: '', ref: '', tags: '' }
|
|
418
|
-
|
|
419
|
+
actionToast.success('fragments.toast.documentLinked')
|
|
419
420
|
return
|
|
420
421
|
}
|
|
421
422
|
|
|
@@ -440,9 +441,9 @@ async function linkDocumentFragment() {
|
|
|
440
441
|
if (linked > 0) {
|
|
441
442
|
// A vue-i18n plural message (count as the plural choice) so Slavic few/many forms
|
|
442
443
|
// render correctly, and the count==1 case reads naturally too.
|
|
443
|
-
toast.
|
|
444
|
-
|
|
445
|
-
|
|
444
|
+
actionToast.success('fragments.toast.documentsLinked', {
|
|
445
|
+
params: { count: linked },
|
|
446
|
+
plural: linked,
|
|
446
447
|
})
|
|
447
448
|
}
|
|
448
449
|
if (firstError) {
|
|
@@ -462,7 +463,7 @@ async function refreshFragment(id: string) {
|
|
|
462
463
|
await withRow(`refresh:${id}`, async () => {
|
|
463
464
|
try {
|
|
464
465
|
await library.refreshDocumentFragment(id)
|
|
465
|
-
|
|
466
|
+
actionToast.success('fragments.toast.refreshed')
|
|
466
467
|
} catch (e) {
|
|
467
468
|
present(e, 'fragments.toast.refreshFailed')
|
|
468
469
|
}
|
|
@@ -519,7 +520,7 @@ async function linkSource() {
|
|
|
519
520
|
// `syncSource` row wrapper): a failure here should surface as a link failure, and
|
|
520
521
|
// the form-level `linkingSource` spinner already covers the whole operation.
|
|
521
522
|
await library.syncSource(source.id)
|
|
522
|
-
|
|
523
|
+
actionToast.success('fragments.toast.sourceLinked')
|
|
523
524
|
} catch (e) {
|
|
524
525
|
present(e, 'fragments.toast.linkSourceFailed')
|
|
525
526
|
} finally {
|
|
@@ -531,13 +532,8 @@ async function syncSource(id: string) {
|
|
|
531
532
|
await withRow(`sync:${id}`, async () => {
|
|
532
533
|
try {
|
|
533
534
|
const result = await library.syncSource(id)
|
|
534
|
-
toast.
|
|
535
|
-
|
|
536
|
-
updated: result.upserted,
|
|
537
|
-
removed: result.tombstoned,
|
|
538
|
-
}),
|
|
539
|
-
icon: 'i-lucide-refresh-cw',
|
|
540
|
-
color: 'info',
|
|
535
|
+
actionToast.success('fragments.toast.synced', {
|
|
536
|
+
params: { updated: result.upserted, removed: result.tombstoned },
|
|
541
537
|
})
|
|
542
538
|
} catch (e) {
|
|
543
539
|
present(e, 'fragments.toast.syncFailed')
|
|
@@ -549,12 +545,9 @@ async function checkSource(id: string) {
|
|
|
549
545
|
await withRow(`check:${id}`, async () => {
|
|
550
546
|
try {
|
|
551
547
|
const status = await library.checkSource(id)
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
: t('fragments.toast.upToDate'),
|
|
556
|
-
icon: status.changed ? 'i-lucide-bell-dot' : 'i-lucide-check',
|
|
557
|
-
})
|
|
548
|
+
actionToast.info(
|
|
549
|
+
status.changed ? 'fragments.toast.changesAvailable' : 'fragments.toast.upToDate',
|
|
550
|
+
)
|
|
558
551
|
} catch (e) {
|
|
559
552
|
present(e, 'fragments.toast.checkSourceFailed')
|
|
560
553
|
}
|
|
@@ -575,7 +568,7 @@ async function unlinkSource(id: string) {
|
|
|
575
568
|
await withRow(`unlink:${id}`, async () => {
|
|
576
569
|
try {
|
|
577
570
|
await library.unlinkSource(id)
|
|
578
|
-
|
|
571
|
+
actionToast.success('fragments.toast.sourceUnlinked')
|
|
579
572
|
} catch (e) {
|
|
580
573
|
present(e, 'fragments.toast.unlinkSourceFailed')
|
|
581
574
|
}
|
|
@@ -771,13 +764,16 @@ async function unlinkSource(id: string) {
|
|
|
771
764
|
</div>
|
|
772
765
|
</div>
|
|
773
766
|
</div>
|
|
774
|
-
<
|
|
775
|
-
|
|
767
|
+
<EmptyState
|
|
768
|
+
v-if="!library.fragments.length"
|
|
769
|
+
compact
|
|
770
|
+
icon="i-lucide-puzzle"
|
|
771
|
+
:title="
|
|
776
772
|
isWorkspace
|
|
777
773
|
? t('fragments.authored.empty.workspace')
|
|
778
774
|
: t('fragments.authored.empty.account')
|
|
779
|
-
|
|
780
|
-
|
|
775
|
+
"
|
|
776
|
+
/>
|
|
781
777
|
|
|
782
778
|
<div class="rounded-md border border-default p-3">
|
|
783
779
|
<p class="mb-2 text-sm font-medium">{{ t('fragments.authored.addTitle') }}</p>
|
|
@@ -887,9 +883,12 @@ async function unlinkSource(id: string) {
|
|
|
887
883
|
/>
|
|
888
884
|
</div>
|
|
889
885
|
</div>
|
|
890
|
-
<
|
|
891
|
-
|
|
892
|
-
|
|
886
|
+
<EmptyState
|
|
887
|
+
v-if="!documentFragments.length"
|
|
888
|
+
compact
|
|
889
|
+
icon="i-lucide-file-text"
|
|
890
|
+
:title="t('fragments.documents.empty')"
|
|
891
|
+
/>
|
|
893
892
|
|
|
894
893
|
<div class="rounded-md border border-default p-3">
|
|
895
894
|
<p class="mb-2 text-sm font-medium">{{ t('fragments.documents.linkTitle') }}</p>
|
|
@@ -1053,9 +1052,12 @@ async function unlinkSource(id: string) {
|
|
|
1053
1052
|
/>
|
|
1054
1053
|
</div>
|
|
1055
1054
|
</div>
|
|
1056
|
-
<
|
|
1057
|
-
|
|
1058
|
-
|
|
1055
|
+
<EmptyState
|
|
1056
|
+
v-if="!library.sources.length"
|
|
1057
|
+
compact
|
|
1058
|
+
icon="i-lucide-git-branch"
|
|
1059
|
+
:title="t('fragments.sources.empty')"
|
|
1060
|
+
/>
|
|
1059
1061
|
|
|
1060
1062
|
<div class="rounded-md border border-default p-3">
|
|
1061
1063
|
<p class="mb-2 text-sm font-medium">{{ t('fragments.sources.linkTitle') }}</p>
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import type { PromptFragment } from '~/types/domain'
|
|
12
12
|
import { buildFragmentCategoryGroups } from '~/utils/fragmentPicker'
|
|
13
13
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
14
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
14
15
|
|
|
15
16
|
const props = withDefaults(
|
|
16
17
|
defineProps<{
|
|
@@ -123,9 +124,12 @@ function manageAccount() {
|
|
|
123
124
|
</UButton>
|
|
124
125
|
</div>
|
|
125
126
|
</template>
|
|
126
|
-
<
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
<EmptyState
|
|
128
|
+
v-else
|
|
129
|
+
compact
|
|
130
|
+
icon="i-lucide-puzzle"
|
|
131
|
+
:title="t('inspector.fragments.pickerEmpty')"
|
|
132
|
+
/>
|
|
129
133
|
|
|
130
134
|
<div class="mt-1 border-t border-default pt-1">
|
|
131
135
|
<UButton
|
|
@@ -14,6 +14,7 @@ import AttemptEntryHeader from '~/components/panels/AttemptEntryHeader.vue'
|
|
|
14
14
|
import GateFailingCheckList from '~/components/gates/GateFailingCheckList.vue'
|
|
15
15
|
import CopyButton from '~/components/common/CopyButton.vue'
|
|
16
16
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
17
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
17
18
|
|
|
18
19
|
const board = useBoardStore()
|
|
19
20
|
const execution = useExecutionStore()
|
|
@@ -213,16 +214,12 @@ const conflictVerdict = computed(() => {
|
|
|
213
214
|
<div class="flex min-h-0 flex-1">
|
|
214
215
|
<!-- Main: the conclusion -->
|
|
215
216
|
<div class="min-w-0 flex-1 overflow-y-auto px-5 py-4">
|
|
216
|
-
<
|
|
217
|
+
<EmptyState
|
|
217
218
|
v-if="!gate"
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
<p class="max-w-sm text-2xs text-dimmed">
|
|
223
|
-
{{ t('gates.noActivityHint') }}
|
|
224
|
-
</p>
|
|
225
|
-
</div>
|
|
219
|
+
:icon="meta.icon"
|
|
220
|
+
:title="t('gates.noActivity')"
|
|
221
|
+
:description="t('gates.noActivityHint')"
|
|
222
|
+
/>
|
|
226
223
|
|
|
227
224
|
<template v-else>
|
|
228
225
|
<!-- Passed -->
|