@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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { showOverrideField } from '~/utils/uiMode'
|
|
3
3
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
4
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
4
5
|
|
|
5
6
|
// The Integrations hub: a single modal that lists the OPTIONAL external systems the WORKSPACE
|
|
6
7
|
// can enable or link in — the ones that feed a run its context (source control, documents,
|
|
@@ -417,9 +418,12 @@ const filteredGroups = computed<IntegrationGroup[]>(() => {
|
|
|
417
418
|
class="w-full"
|
|
418
419
|
/>
|
|
419
420
|
|
|
420
|
-
<
|
|
421
|
-
|
|
422
|
-
|
|
421
|
+
<EmptyState
|
|
422
|
+
v-if="!filteredGroups.length"
|
|
423
|
+
compact
|
|
424
|
+
icon="i-lucide-search-x"
|
|
425
|
+
:title="t('layout.integrationsHub.noMatches', { query })"
|
|
426
|
+
/>
|
|
423
427
|
|
|
424
428
|
<section v-for="group in filteredGroups" :key="group.title">
|
|
425
429
|
<SectionLabel as="h3" class="mb-2 px-1">
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
// "Back to Model providers" control (IntegrationBackTitle). Layout mirrors the Integrations
|
|
14
14
|
// hub row-for-row so the two read as siblings.
|
|
15
15
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
16
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
16
17
|
|
|
17
18
|
const { t } = useI18n()
|
|
18
19
|
const ui = useUiStore()
|
|
@@ -197,9 +198,12 @@ const filteredGroups = computed<ProviderGroup[]>(() => {
|
|
|
197
198
|
class="w-full"
|
|
198
199
|
/>
|
|
199
200
|
|
|
200
|
-
<
|
|
201
|
-
|
|
202
|
-
|
|
201
|
+
<EmptyState
|
|
202
|
+
v-if="!filteredGroups.length"
|
|
203
|
+
compact
|
|
204
|
+
icon="i-lucide-search-x"
|
|
205
|
+
:title="t('layout.modelProvidersHub.noMatches', { query })"
|
|
206
|
+
/>
|
|
203
207
|
|
|
204
208
|
<section v-for="group in filteredGroups" :key="group.title">
|
|
205
209
|
<SectionLabel as="h3" class="mb-2 px-1">
|
|
@@ -16,7 +16,7 @@ const ui = useUiStore()
|
|
|
16
16
|
const access = useWorkspaceAccess()
|
|
17
17
|
const execution = useExecutionStore()
|
|
18
18
|
const trackRecords = useMergeTrackRecordsStore()
|
|
19
|
-
const
|
|
19
|
+
const actionToast = useActionToast()
|
|
20
20
|
const { present } = usePipelineErrorToast()
|
|
21
21
|
|
|
22
22
|
const busy = ref<string | null>(null)
|
|
@@ -197,11 +197,7 @@ async function act(n: Notification) {
|
|
|
197
197
|
// Only the merge cards carry a tag; passing `undefined` elsewhere keeps the historical
|
|
198
198
|
// no-body act, so a non-merge card's action is completely unchanged.
|
|
199
199
|
await notifications.act(n.id, collectsEffort(n) ? effortFor(n) : undefined)
|
|
200
|
-
toast.
|
|
201
|
-
title: t('layout.notifications.toast.acted'),
|
|
202
|
-
color: 'success',
|
|
203
|
-
icon: 'i-lucide-check',
|
|
204
|
-
})
|
|
200
|
+
actionToast.success('layout.notifications.toast.acted')
|
|
205
201
|
} catch (e) {
|
|
206
202
|
present(e, 'layout.notifications.toast.actFailed')
|
|
207
203
|
} finally {
|
|
@@ -213,11 +209,7 @@ async function dismiss(n: Notification) {
|
|
|
213
209
|
busy.value = n.id
|
|
214
210
|
try {
|
|
215
211
|
await notifications.dismiss(n.id)
|
|
216
|
-
toast.
|
|
217
|
-
title: t('layout.notifications.toast.dismissed'),
|
|
218
|
-
color: 'neutral',
|
|
219
|
-
icon: 'i-lucide-check',
|
|
220
|
-
})
|
|
212
|
+
actionToast.success('layout.notifications.toast.dismissed')
|
|
221
213
|
} catch (e) {
|
|
222
214
|
present(e, 'layout.notifications.toast.dismissFailed')
|
|
223
215
|
} finally {
|
|
@@ -21,6 +21,7 @@ import UserMenu from '~/components/auth/UserMenu.vue'
|
|
|
21
21
|
import { useViewport } from '~/composables/useViewport'
|
|
22
22
|
import type { NavContribution } from '~/modular/nav-contributions'
|
|
23
23
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
24
|
+
import WorkViewSwitcher from '~/components/layout/WorkViewSwitcher.vue'
|
|
24
25
|
|
|
25
26
|
const { t } = useI18n()
|
|
26
27
|
|
|
@@ -227,6 +228,10 @@ watch(
|
|
|
227
228
|
</div>
|
|
228
229
|
|
|
229
230
|
<div class="contents" @click="onNavAction">
|
|
231
|
+
<!-- The two views of the board (issue #2258), first because they decide what the main
|
|
232
|
+
area shows. -->
|
|
233
|
+
<WorkViewSwitcher :collapsed="railed" />
|
|
234
|
+
|
|
230
235
|
<!-- Command bar launcher (⌘K) — the primary way to create blocks / pipelines
|
|
231
236
|
and reach every action below. -->
|
|
232
237
|
<UButton
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { WorkView } from '~/utils/workView'
|
|
3
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The sidebar's "Views" section: the queue and the canvas, as two views of one board.
|
|
7
|
+
*
|
|
8
|
+
* A view SWITCHER, not a list of destinations, which is why it is not a `nav` contribution: a
|
|
9
|
+
* contribution opens something, and these change what the main area shows, so they need the
|
|
10
|
+
* selected state a contribution has no shape for. Shown in every tier and every role: which view
|
|
11
|
+
* a person works in is their choice, and neither view is an override of the other.
|
|
12
|
+
*/
|
|
13
|
+
defineProps<{ collapsed: boolean }>()
|
|
14
|
+
|
|
15
|
+
const { t } = useI18n()
|
|
16
|
+
const views = useWorkViewStore()
|
|
17
|
+
const queue = useWorkspaceQueueStore()
|
|
18
|
+
|
|
19
|
+
const ITEMS: { view: WorkView; icon: string; labelKey: string }[] = [
|
|
20
|
+
{ view: 'queue', icon: 'i-lucide-list-checks', labelKey: 'views.queue' },
|
|
21
|
+
{ view: 'board', icon: 'i-lucide-map', labelKey: 'views.board' },
|
|
22
|
+
]
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<template>
|
|
26
|
+
<section data-testid="work-view-switcher">
|
|
27
|
+
<SectionLabel v-if="!collapsed" as="h2" class="mb-2 px-1">
|
|
28
|
+
{{ t('views.title') }}
|
|
29
|
+
</SectionLabel>
|
|
30
|
+
<div class="space-y-1.5">
|
|
31
|
+
<UButton
|
|
32
|
+
v-for="item in ITEMS"
|
|
33
|
+
:key="item.view"
|
|
34
|
+
:block="!collapsed"
|
|
35
|
+
:square="collapsed"
|
|
36
|
+
size="sm"
|
|
37
|
+
:color="views.view === item.view ? 'primary' : 'neutral'"
|
|
38
|
+
:variant="views.view === item.view ? 'soft' : 'ghost'"
|
|
39
|
+
:icon="item.icon"
|
|
40
|
+
class="w-full"
|
|
41
|
+
:class="collapsed ? 'justify-center' : 'justify-start'"
|
|
42
|
+
:aria-label="collapsed ? t(item.labelKey) : undefined"
|
|
43
|
+
:aria-current="views.view === item.view ? 'page' : undefined"
|
|
44
|
+
:title="collapsed ? t(item.labelKey) : undefined"
|
|
45
|
+
:data-testid="`work-view-${item.view}`"
|
|
46
|
+
@click="views.show(item.view)"
|
|
47
|
+
>
|
|
48
|
+
<template v-if="!collapsed">
|
|
49
|
+
<span class="flex-1 truncate text-start">{{ t(item.labelKey) }}</span>
|
|
50
|
+
<!-- The queue's count: tasks an agent cannot continue until a person acts. -->
|
|
51
|
+
<UBadge
|
|
52
|
+
v-if="item.view === 'queue' && queue.needsYouCount > 0"
|
|
53
|
+
size="sm"
|
|
54
|
+
color="warning"
|
|
55
|
+
variant="subtle"
|
|
56
|
+
data-testid="work-view-queue-count"
|
|
57
|
+
>
|
|
58
|
+
{{ queue.needsYouCount }}
|
|
59
|
+
</UBadge>
|
|
60
|
+
</template>
|
|
61
|
+
</UButton>
|
|
62
|
+
</div>
|
|
63
|
+
</section>
|
|
64
|
+
</template>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed, onMounted, ref, watch } from 'vue'
|
|
3
3
|
import type { WorkspaceAccessMode, WorkspaceRole } from '~/types/domain'
|
|
4
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
4
5
|
|
|
5
6
|
// Workspace-membership management (workspace-rbac initiative, slice 9). The tier BELOW
|
|
6
7
|
// account tenancy: an account admin restricts a board to an explicit member list (with
|
|
@@ -16,7 +17,7 @@ const workspace = useWorkspaceStore()
|
|
|
16
17
|
const members = useWorkspaceMembersStore()
|
|
17
18
|
const accounts = useAccountsStore()
|
|
18
19
|
const auth = useAuthStore()
|
|
19
|
-
const
|
|
20
|
+
const actionToast = useActionToast()
|
|
20
21
|
const { present } = usePipelineErrorToast()
|
|
21
22
|
const { t } = useI18n()
|
|
22
23
|
const { confirmAction, toastDone } = useConfirmAction()
|
|
@@ -108,7 +109,7 @@ async function addMember() {
|
|
|
108
109
|
await members.add(props.workspaceId, userId, addRole.value)
|
|
109
110
|
addUserId.value = undefined
|
|
110
111
|
addRole.value = 'member'
|
|
111
|
-
|
|
112
|
+
actionToast.success('layout.workspaceMembers.add.added')
|
|
112
113
|
} catch (e) {
|
|
113
114
|
present(e, 'layout.workspaceMembers.errors.add')
|
|
114
115
|
} finally {
|
|
@@ -173,7 +174,9 @@ function memberLabel(userId: string, name?: string | null, email?: string | null
|
|
|
173
174
|
<h3 class="mb-2 font-semibold text-highlighted">
|
|
174
175
|
{{ t('layout.workspaceMembers.roster.title') }}
|
|
175
176
|
</h3>
|
|
176
|
-
<
|
|
177
|
+
<div v-if="!rosterReady" class="space-y-1">
|
|
178
|
+
<USkeleton v-for="i in 3" :key="i" class="h-8 w-full" />
|
|
179
|
+
</div>
|
|
177
180
|
<ul v-else class="space-y-1" data-testid="workspace-members-roster">
|
|
178
181
|
<li
|
|
179
182
|
v-for="m in members.members"
|
|
@@ -206,8 +209,12 @@ function memberLabel(userId: string, name?: string | null, email?: string | null
|
|
|
206
209
|
/>
|
|
207
210
|
</span>
|
|
208
211
|
</li>
|
|
209
|
-
<li v-if="members.members.length === 0"
|
|
210
|
-
|
|
212
|
+
<li v-if="members.members.length === 0">
|
|
213
|
+
<EmptyState
|
|
214
|
+
compact
|
|
215
|
+
icon="i-lucide-users"
|
|
216
|
+
:title="t('layout.workspaceMembers.roster.empty')"
|
|
217
|
+
/>
|
|
211
218
|
</li>
|
|
212
219
|
</ul>
|
|
213
220
|
</section>
|
|
@@ -10,6 +10,7 @@ import { computed, ref, watch } from 'vue'
|
|
|
10
10
|
import { useModalBehavior } from '@modular-vue/core'
|
|
11
11
|
import type { ArtifactBlobs } from '~/composables/useArtifactBlobs'
|
|
12
12
|
import IconButton from '~/components/common/IconButton.vue'
|
|
13
|
+
import Spinner from '~/components/common/Spinner.vue'
|
|
13
14
|
import { FULL_BLEED_TAKEOVER_CLASS } from '~/utils/safeArea'
|
|
14
15
|
|
|
15
16
|
interface LightboxItem {
|
|
@@ -273,10 +274,10 @@ onBeforeUnmount(() => window.removeEventListener('keydown', onKey, true))
|
|
|
273
274
|
@pointercancel="onPointerUp"
|
|
274
275
|
/>
|
|
275
276
|
<div v-else class="flex flex-col items-center gap-2 text-dimmed">
|
|
276
|
-
<
|
|
277
|
-
:name="state === 'error' ? 'i-lucide-image-off' :
|
|
277
|
+
<Spinner
|
|
278
|
+
:name="state === 'error' ? 'i-lucide-image-off' : undefined"
|
|
279
|
+
:spinning="state !== 'error'"
|
|
278
280
|
class="h-8 w-8"
|
|
279
|
-
:class="state === 'error' ? '' : 'animate-spin'"
|
|
280
281
|
/>
|
|
281
282
|
<p class="text-xs">
|
|
282
283
|
{{ state === 'error' ? t('media.lightbox.failed') : t('media.lightbox.loading') }}
|
|
@@ -30,7 +30,7 @@ import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
|
30
30
|
const ui = useUiStore()
|
|
31
31
|
const notifications = useNotificationsStore()
|
|
32
32
|
const slack = useSlackStore()
|
|
33
|
-
const
|
|
33
|
+
const actionToast = useActionToast()
|
|
34
34
|
const { present } = usePipelineErrorToast()
|
|
35
35
|
const { t } = useI18n()
|
|
36
36
|
|
|
@@ -119,11 +119,7 @@ async function save() {
|
|
|
119
119
|
busy.value = true
|
|
120
120
|
try {
|
|
121
121
|
await notifications.updateSettings(matrix)
|
|
122
|
-
toast.
|
|
123
|
-
title: t('notificationSettings.toast.saved'),
|
|
124
|
-
icon: 'i-lucide-check',
|
|
125
|
-
color: 'success',
|
|
126
|
-
})
|
|
122
|
+
actionToast.success('notificationSettings.toast.saved')
|
|
127
123
|
} catch (e) {
|
|
128
124
|
present(e, 'notificationSettings.error.save')
|
|
129
125
|
} finally {
|
|
@@ -167,11 +163,8 @@ function resetToDefaults() {
|
|
|
167
163
|
</UButton>
|
|
168
164
|
</div>
|
|
169
165
|
|
|
170
|
-
<div
|
|
171
|
-
v-
|
|
172
|
-
class="rounded-lg border border-muted bg-elevated/40 p-3 text-xs text-muted"
|
|
173
|
-
>
|
|
174
|
-
{{ t('common.loading') }}
|
|
166
|
+
<div v-else-if="!editable" class="space-y-1">
|
|
167
|
+
<USkeleton v-for="n in 4" :key="n" class="h-10 w-full" />
|
|
175
168
|
</div>
|
|
176
169
|
|
|
177
170
|
<template v-else>
|
|
@@ -6,6 +6,7 @@ import { filterToolCallsByOutcome, formatMs } from '~/utils/observability'
|
|
|
6
6
|
import { agentKindMeta } from '~/utils/catalog'
|
|
7
7
|
import OutcomeFilterChips from '~/components/observability/OutcomeFilterChips.vue'
|
|
8
8
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
9
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
9
10
|
|
|
10
11
|
// The tool-call TRAJECTORY drill-down: what the run's agents DID, oldest first, in the order
|
|
11
12
|
// they did it. The sibling of the model-call list, and the one that holds the failures no LLM
|
|
@@ -153,13 +154,9 @@ function prettyArgs(raw: string): string {
|
|
|
153
154
|
|
|
154
155
|
<!-- Every state below is gated on having NOTHING to show: rows already in hand outrank a
|
|
155
156
|
read still in flight behind them, and outrank one that failed. -->
|
|
156
|
-
<
|
|
157
|
-
v-
|
|
158
|
-
|
|
159
|
-
>
|
|
160
|
-
<UIcon name="i-lucide-loader-circle" class="h-4 w-4 animate-spin" />
|
|
161
|
-
{{ t('observability.toolCalls.loading') }}
|
|
162
|
-
</p>
|
|
157
|
+
<div v-if="source.loading && !visible.length" class="space-y-2">
|
|
158
|
+
<USkeleton v-for="n in 3" :key="n" class="h-10 w-full rounded-xl" />
|
|
159
|
+
</div>
|
|
163
160
|
<div
|
|
164
161
|
v-else-if="source.error && !visible.length"
|
|
165
162
|
class="flex flex-col items-center gap-3 rounded-lg border border-dashed border-app-error-900/60 py-6 text-center text-sm text-app-error-400"
|
|
@@ -178,20 +175,18 @@ function prettyArgs(raw: string): string {
|
|
|
178
175
|
</div>
|
|
179
176
|
<!-- "The run made no tool calls" is a claim about the RUN, so it comes off the aggregate,
|
|
180
177
|
never off an empty prefix that may simply not have loaded. -->
|
|
181
|
-
<
|
|
178
|
+
<EmptyState
|
|
182
179
|
v-else-if="!counts.all"
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
</p>
|
|
180
|
+
icon="i-lucide-wrench"
|
|
181
|
+
:title="t('observability.toolCalls.none')"
|
|
182
|
+
/>
|
|
187
183
|
<!-- Narrowed to nothing is a different statement from recorded nothing, and it is the more
|
|
188
184
|
reassuring of the two: the operator asked for the failures and there are none. -->
|
|
189
|
-
<
|
|
185
|
+
<EmptyState
|
|
190
186
|
v-else-if="!visible.length"
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
</p>
|
|
187
|
+
icon="i-lucide-list-filter"
|
|
188
|
+
:title="t('observability.toolCalls.noneMatching')"
|
|
189
|
+
/>
|
|
195
190
|
|
|
196
191
|
<template v-else>
|
|
197
192
|
<!-- What this view is bounded by, when it is. A cap nobody can see is a prefix read as a
|
|
@@ -31,6 +31,7 @@ import InputGateNotice from '~/components/inputGate/InputGateNotice.vue'
|
|
|
31
31
|
import RunDetailLoadState from '~/components/panels/RunDetailLoadState.vue'
|
|
32
32
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
33
33
|
import IconButton from '~/components/common/IconButton.vue'
|
|
34
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
34
35
|
import { FULL_BLEED_TAKEOVER_CLASS } from '~/utils/safeArea'
|
|
35
36
|
|
|
36
37
|
// Detail overlay for a single pipeline step. Opened by clicking an agent in the
|
|
@@ -822,12 +823,11 @@ async function copyOutput() {
|
|
|
822
823
|
</section>
|
|
823
824
|
</template>
|
|
824
825
|
|
|
825
|
-
<
|
|
826
|
+
<EmptyState
|
|
826
827
|
v-else
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
</p>
|
|
828
|
+
icon="i-lucide-file-text"
|
|
829
|
+
:title="t('panels.stepDetail.noProseOutput')"
|
|
830
|
+
/>
|
|
831
831
|
</div>
|
|
832
832
|
</div>
|
|
833
833
|
</div>
|
|
@@ -12,6 +12,7 @@ import ResultWindowShell from '~/components/panels/ResultWindowShell.vue'
|
|
|
12
12
|
import MarkdownProse from '~/components/common/MarkdownProse.vue'
|
|
13
13
|
import CopyButton from '~/components/common/CopyButton.vue'
|
|
14
14
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
15
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
15
16
|
|
|
16
17
|
const board = useBoardStore()
|
|
17
18
|
const execution = useExecutionStore()
|
|
@@ -87,16 +88,12 @@ const customJson = computed<string | null>(() => {
|
|
|
87
88
|
><code>{{ customJson }}</code></pre>
|
|
88
89
|
</template>
|
|
89
90
|
|
|
90
|
-
<
|
|
91
|
+
<EmptyState
|
|
91
92
|
v-else-if="!step?.output"
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
<p class="max-w-sm text-2xs text-dimmed">
|
|
97
|
-
{{ t('panels.structuredResult.noResultHint') }}
|
|
98
|
-
</p>
|
|
99
|
-
</div>
|
|
93
|
+
icon="i-lucide-braces"
|
|
94
|
+
:title="t('panels.structuredResult.noResult')"
|
|
95
|
+
:description="t('panels.structuredResult.noResultHint')"
|
|
96
|
+
/>
|
|
100
97
|
</div>
|
|
101
98
|
|
|
102
99
|
<!-- Sidebar: shared run metadata + observability rollup -->
|
|
@@ -11,6 +11,7 @@ import BootstrapRunSteps from '~/components/bootstrap/BootstrapRunSteps.vue'
|
|
|
11
11
|
import { BLUEPRINT_AGENT_KIND } from '@cat-factory/contracts'
|
|
12
12
|
import { VCS_PROVIDER_ICONS } from '~/utils/vcs'
|
|
13
13
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
14
|
+
import Spinner from '~/components/common/Spinner.vue'
|
|
14
15
|
|
|
15
16
|
const board = useBoardStore()
|
|
16
17
|
const pipelines = usePipelinesStore()
|
|
@@ -500,7 +501,7 @@ const showOriginalDescription = ref(false)
|
|
|
500
501
|
>
|
|
501
502
|
<div class="flex items-center justify-between gap-2">
|
|
502
503
|
<span class="flex items-center gap-1.5 text-xs text-app-warning-300">
|
|
503
|
-
<
|
|
504
|
+
<Spinner class="h-3.5 w-3.5" />
|
|
504
505
|
{{ t('panels.inspector.bootstrapping') }}
|
|
505
506
|
</span>
|
|
506
507
|
<div class="flex items-center gap-1.5">
|
|
@@ -12,6 +12,7 @@ import StepRunMeta from '~/components/panels/StepRunMeta.vue'
|
|
|
12
12
|
import ResultWindowShell from '~/components/panels/ResultWindowShell.vue'
|
|
13
13
|
import MarkdownProse from '~/components/common/MarkdownProse.vue'
|
|
14
14
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
15
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
15
16
|
|
|
16
17
|
const board = useBoardStore()
|
|
17
18
|
const execution = useExecutionStore()
|
|
@@ -275,13 +276,11 @@ const reasonText = computed(() => {
|
|
|
275
276
|
:text="step.output"
|
|
276
277
|
class="text-sm leading-relaxed text-toned"
|
|
277
278
|
/>
|
|
278
|
-
<
|
|
279
|
+
<EmptyState
|
|
279
280
|
v-else
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
<p class="text-sm">{{ t('panels.mergerResult.noResult') }}</p>
|
|
284
|
-
</div>
|
|
281
|
+
icon="i-lucide-git-pull-request"
|
|
282
|
+
:title="t('panels.mergerResult.noResult')"
|
|
283
|
+
/>
|
|
285
284
|
</div>
|
|
286
285
|
|
|
287
286
|
<!-- Sidebar: shared run metadata. -->
|
|
@@ -32,6 +32,7 @@ import RunFailureSummary from '~/components/observability/RunFailureSummary.vue'
|
|
|
32
32
|
import ToolCallList from '~/components/observability/ToolCallList.vue'
|
|
33
33
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
34
34
|
import IconButton from '~/components/common/IconButton.vue'
|
|
35
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
35
36
|
import { FULL_BLEED_TAKEOVER_CLASS } from '~/utils/safeArea'
|
|
36
37
|
|
|
37
38
|
/** No run selected: the same empty, NOT-truncated trajectory the store answers with. */
|
|
@@ -844,13 +845,9 @@ function exportJson() {
|
|
|
844
845
|
</section>
|
|
845
846
|
|
|
846
847
|
<!-- states -->
|
|
847
|
-
<
|
|
848
|
-
v-
|
|
849
|
-
|
|
850
|
-
>
|
|
851
|
-
<UIcon name="i-lucide-loader-circle" class="h-4 w-4 animate-spin" />
|
|
852
|
-
{{ t('observability.loadingActivity') }}
|
|
853
|
-
</p>
|
|
848
|
+
<div v-if="loading && !calls.length" class="space-y-2">
|
|
849
|
+
<USkeleton v-for="n in 3" :key="n" class="h-10 w-full rounded-xl" />
|
|
850
|
+
</div>
|
|
854
851
|
<div
|
|
855
852
|
v-else-if="error"
|
|
856
853
|
class="flex flex-col items-center gap-3 rounded-lg border border-dashed border-app-error-900/60 py-6 text-center text-sm text-app-error-400"
|
|
@@ -867,12 +864,11 @@ function exportJson() {
|
|
|
867
864
|
{{ t('common.retry') }}
|
|
868
865
|
</UButton>
|
|
869
866
|
</div>
|
|
870
|
-
<
|
|
867
|
+
<EmptyState
|
|
871
868
|
v-else-if="!calls.length"
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
</p>
|
|
869
|
+
icon="i-lucide-activity"
|
|
870
|
+
:title="t('observability.noCalls')"
|
|
871
|
+
/>
|
|
876
872
|
|
|
877
873
|
<!-- per-call list, narrowable by outcome -->
|
|
878
874
|
<template v-else>
|
|
@@ -886,12 +882,11 @@ function exportJson() {
|
|
|
886
882
|
<!-- Narrowed to nothing reads differently from recorded nothing, and on this
|
|
887
883
|
surface it is the good news: the operator asked for the failures and there
|
|
888
884
|
are none. -->
|
|
889
|
-
<
|
|
885
|
+
<EmptyState
|
|
890
886
|
v-if="!visibleCalls.length"
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
</p>
|
|
887
|
+
icon="i-lucide-list-filter"
|
|
888
|
+
:title="t('observability.noCallsMatching')"
|
|
889
|
+
/>
|
|
895
890
|
|
|
896
891
|
<ul v-else class="space-y-2">
|
|
897
892
|
<li
|
|
@@ -1092,13 +1087,9 @@ function exportJson() {
|
|
|
1092
1087
|
|
|
1093
1088
|
<!-- Provided context: the complete context each container agent was given. -->
|
|
1094
1089
|
<div v-else-if="view === 'context'" class="mx-auto max-w-4xl space-y-5">
|
|
1095
|
-
<
|
|
1096
|
-
v-
|
|
1097
|
-
|
|
1098
|
-
>
|
|
1099
|
-
<UIcon name="i-lucide-loader-circle" class="h-4 w-4 animate-spin" />
|
|
1100
|
-
{{ t('observability.loadingContext') }}
|
|
1101
|
-
</p>
|
|
1090
|
+
<div v-if="contextLoading && !contextSnapshots.length" class="space-y-2">
|
|
1091
|
+
<USkeleton v-for="n in 3" :key="n" class="h-10 w-full rounded-xl" />
|
|
1092
|
+
</div>
|
|
1102
1093
|
<div
|
|
1103
1094
|
v-else-if="contextError && !contextSnapshots.length"
|
|
1104
1095
|
class="flex flex-col items-center gap-3 rounded-lg border border-dashed border-app-error-900/60 py-8 text-center text-sm text-app-error-400"
|
|
@@ -1115,12 +1106,11 @@ function exportJson() {
|
|
|
1115
1106
|
{{ t('common.retry') }}
|
|
1116
1107
|
</UButton>
|
|
1117
1108
|
</div>
|
|
1118
|
-
<
|
|
1109
|
+
<EmptyState
|
|
1119
1110
|
v-else-if="!contextSnapshots.length"
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
</p>
|
|
1111
|
+
icon="i-lucide-file-text"
|
|
1112
|
+
:title="t('observability.noContext')"
|
|
1113
|
+
/>
|
|
1124
1114
|
|
|
1125
1115
|
<ul v-else class="space-y-2">
|
|
1126
1116
|
<li
|
|
@@ -1251,19 +1241,14 @@ function exportJson() {
|
|
|
1251
1241
|
</span>
|
|
1252
1242
|
</section>
|
|
1253
1243
|
|
|
1254
|
-
<
|
|
1255
|
-
v-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
<UIcon name="i-lucide-loader-circle" class="h-4 w-4 animate-spin" />
|
|
1259
|
-
{{ t('observability.loadingSearch') }}
|
|
1260
|
-
</p>
|
|
1261
|
-
<p
|
|
1244
|
+
<div v-if="searchLoading && !searchQueries.length" class="space-y-2">
|
|
1245
|
+
<USkeleton v-for="n in 3" :key="n" class="h-10 w-full rounded-xl" />
|
|
1246
|
+
</div>
|
|
1247
|
+
<EmptyState
|
|
1262
1248
|
v-else-if="!searchQueries.length"
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
</p>
|
|
1249
|
+
icon="i-lucide-search"
|
|
1250
|
+
:title="t('observability.noSearch')"
|
|
1251
|
+
/>
|
|
1267
1252
|
|
|
1268
1253
|
<div v-else>
|
|
1269
1254
|
<SectionLabel class="mb-2">
|