@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
|
@@ -19,6 +19,8 @@ import {
|
|
|
19
19
|
trendMagnitude,
|
|
20
20
|
} from './ReportsPanel.logic'
|
|
21
21
|
import ReportsSpendBreakdown from '~/components/panels/ReportsSpendBreakdown.vue'
|
|
22
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
23
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
22
24
|
|
|
23
25
|
// Reports: cross-cutting usage analytics for the active account — where the spend and the
|
|
24
26
|
// work actually go. Spend per model and agent kind, spend + run activity per workspace /
|
|
@@ -136,6 +138,14 @@ const maxRuns = computed(() => maxOf(activityByDimension.value, (row) => row.run
|
|
|
136
138
|
|
|
137
139
|
/** Boards the filter offers — the active account's, since the report is account-scoped. */
|
|
138
140
|
const boards = computed(() => workspace.accountWorkspaces)
|
|
141
|
+
// "Every board" is a NAMED sentinel, not an empty string: an empty string is what a Select
|
|
142
|
+
// reserves for "nothing selected", and Reka throws on an item that carries one. The store holds
|
|
143
|
+
// the same state as null, so the two are mapped at the boundary below.
|
|
144
|
+
const ALL_BOARDS = 'all'
|
|
145
|
+
const boardFilterItems = computed(() => [
|
|
146
|
+
{ label: t('reports.filter.allBoards'), value: ALL_BOARDS },
|
|
147
|
+
...boards.value.map((board) => ({ label: board.name, value: board.id })),
|
|
148
|
+
])
|
|
139
149
|
|
|
140
150
|
function trendTooltip(point: { start: number; meteredCost: number; subscriptionCost: number }) {
|
|
141
151
|
return `${d(new Date(point.start), 'short')} · ${t('reports.legend.metered')} ${money(point.meteredCost)} · ${t('reports.legend.subscription')} ${money(point.subscriptionCost)}`
|
|
@@ -205,55 +215,52 @@ watch(
|
|
|
205
215
|
</div>
|
|
206
216
|
<!-- Filters in ONE row above the charts: window, then board scope. -->
|
|
207
217
|
<div class="ms-auto flex flex-wrap items-center gap-1.5">
|
|
208
|
-
<
|
|
209
|
-
|
|
210
|
-
:
|
|
218
|
+
<USelect
|
|
219
|
+
:model-value="reports.workspaceFilter ?? ALL_BOARDS"
|
|
220
|
+
:items="boardFilterItems"
|
|
221
|
+
size="xs"
|
|
211
222
|
:aria-label="t('reports.filter.board')"
|
|
212
223
|
data-testid="reports-board-filter"
|
|
213
|
-
@
|
|
214
|
-
reports.setWorkspaceFilter(
|
|
224
|
+
@update:model-value="
|
|
225
|
+
reports.setWorkspaceFilter($event === ALL_BOARDS ? null : String($event))
|
|
215
226
|
"
|
|
227
|
+
/>
|
|
228
|
+
<UTabs
|
|
229
|
+
:model-value="reports.window"
|
|
230
|
+
:items="WINDOWS"
|
|
231
|
+
:content="false"
|
|
232
|
+
size="xs"
|
|
233
|
+
class="me-1"
|
|
234
|
+
@update:model-value="reports.setWindow($event as ReportWindow)"
|
|
216
235
|
>
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
:data-testid="`reports-window-${opt.value}`"
|
|
233
|
-
@click="reports.setWindow(opt.value)"
|
|
234
|
-
>
|
|
235
|
-
{{ opt.label }}
|
|
236
|
-
</button>
|
|
237
|
-
</div>
|
|
238
|
-
<button
|
|
239
|
-
class="rounded-lg border border-default p-1.5 text-muted transition hover:text-default"
|
|
240
|
-
:aria-label="t('reports.refresh')"
|
|
241
|
-
:title="t('reports.refresh')"
|
|
236
|
+
<!-- UTabs renders its own triggers and forwards nothing from an item, so this
|
|
237
|
+
slot is the one place a stable per-window selector can live. -->
|
|
238
|
+
<template #default="{ item }">
|
|
239
|
+
<span :data-testid="`reports-window-${item.value}`">{{ item.label }}</span>
|
|
240
|
+
</template>
|
|
241
|
+
</UTabs>
|
|
242
|
+
<IconButton
|
|
243
|
+
color="neutral"
|
|
244
|
+
variant="ghost"
|
|
245
|
+
icon="i-lucide-refresh-cw"
|
|
246
|
+
:label="t('reports.refresh')"
|
|
247
|
+
:ui="{
|
|
248
|
+
base: 'rounded-lg border border-default p-1.5 text-muted transition hover:text-default',
|
|
249
|
+
leadingIcon: loading ? 'h-4 w-4 animate-spin' : 'h-4 w-4',
|
|
250
|
+
}"
|
|
242
251
|
@click="refresh"
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
252
|
+
/>
|
|
253
|
+
<IconButton
|
|
254
|
+
color="neutral"
|
|
255
|
+
variant="ghost"
|
|
256
|
+
icon="i-lucide-x"
|
|
257
|
+
:label="t('common.close')"
|
|
258
|
+
:ui="{
|
|
259
|
+
base: 'rounded-lg border border-default p-1.5 text-muted transition hover:text-default',
|
|
260
|
+
leadingIcon: 'h-4 w-4',
|
|
261
|
+
}"
|
|
253
262
|
@click="close"
|
|
254
|
-
|
|
255
|
-
<UIcon name="i-lucide-x" class="h-4 w-4" />
|
|
256
|
-
</button>
|
|
263
|
+
/>
|
|
257
264
|
</div>
|
|
258
265
|
</header>
|
|
259
266
|
|
|
@@ -264,12 +271,14 @@ watch(
|
|
|
264
271
|
>
|
|
265
272
|
<p>{{ t('reports.error') }}</p>
|
|
266
273
|
<p v-if="error" class="mt-1 text-xs text-app-error-300/80">{{ error }}</p>
|
|
267
|
-
<
|
|
274
|
+
<UButton
|
|
275
|
+
color="neutral"
|
|
276
|
+
variant="ghost"
|
|
268
277
|
class="mt-2 rounded-md border border-app-error-700 px-3 py-1 text-xs hover:bg-app-error-900/40"
|
|
269
278
|
@click="refresh"
|
|
270
279
|
>
|
|
271
280
|
{{ t('reports.retry') }}
|
|
272
|
-
</
|
|
281
|
+
</UButton>
|
|
273
282
|
</div>
|
|
274
283
|
|
|
275
284
|
<div v-else-if="loading && !view" class="py-16 text-center text-sm text-muted">
|
|
@@ -277,7 +286,7 @@ watch(
|
|
|
277
286
|
</div>
|
|
278
287
|
|
|
279
288
|
<div v-else-if="view" class="mx-auto flex max-w-5xl flex-col gap-6">
|
|
280
|
-
<p class="text-
|
|
289
|
+
<p class="text-2xs text-dimmed">
|
|
281
290
|
{{
|
|
282
291
|
t('reports.period', {
|
|
283
292
|
from: d(new Date(view.since), 'short'),
|
|
@@ -308,7 +317,7 @@ watch(
|
|
|
308
317
|
</p>
|
|
309
318
|
<p
|
|
310
319
|
v-else-if="rollupState === 'current'"
|
|
311
|
-
class="text-
|
|
320
|
+
class="text-2xs text-dimmed"
|
|
312
321
|
data-testid="reports-rollup-current"
|
|
313
322
|
>
|
|
314
323
|
{{
|
|
@@ -320,9 +329,9 @@ watch(
|
|
|
320
329
|
|
|
321
330
|
<!-- Headline totals. A stat tile, not a chart: these are single numbers. -->
|
|
322
331
|
<section>
|
|
323
|
-
<h2 class="mb-2
|
|
332
|
+
<SectionLabel as="h2" class="mb-2">
|
|
324
333
|
{{ t('reports.totals.title') }}
|
|
325
|
-
</
|
|
334
|
+
</SectionLabel>
|
|
326
335
|
<div class="grid grid-cols-2 gap-3 sm:grid-cols-4">
|
|
327
336
|
<div class="rounded-lg border border-default bg-default/40 p-3">
|
|
328
337
|
<p
|
|
@@ -352,16 +361,16 @@ watch(
|
|
|
352
361
|
<p class="text-xs text-dimmed">{{ t('reports.totals.tokens') }}</p>
|
|
353
362
|
</div>
|
|
354
363
|
</div>
|
|
355
|
-
<p class="mt-1.5 text-
|
|
364
|
+
<p class="mt-1.5 text-3xs text-dimmed">
|
|
356
365
|
{{ t('reports.totals.illustrative') }}
|
|
357
366
|
</p>
|
|
358
367
|
</section>
|
|
359
368
|
|
|
360
369
|
<!-- Spend over time. One axis, two stacked series, legend always present. -->
|
|
361
370
|
<section>
|
|
362
|
-
<h2 class="mb-2
|
|
371
|
+
<SectionLabel as="h2" class="mb-2">
|
|
363
372
|
{{ t('reports.trend.title') }}
|
|
364
|
-
</
|
|
373
|
+
</SectionLabel>
|
|
365
374
|
<div class="rounded-lg border border-default bg-default/40 p-4">
|
|
366
375
|
<div v-if="!hasSpend" class="py-6 text-center text-xs text-dimmed">
|
|
367
376
|
{{ t('reports.trend.empty') }}
|
|
@@ -383,7 +392,7 @@ watch(
|
|
|
383
392
|
/>
|
|
384
393
|
</div>
|
|
385
394
|
</div>
|
|
386
|
-
<div class="mt-2 flex items-center gap-4 text-
|
|
395
|
+
<div class="mt-2 flex items-center gap-4 text-2xs text-dimmed">
|
|
387
396
|
<span class="flex items-center gap-1" :title="t('reports.legend.meteredHint')">
|
|
388
397
|
<span class="h-2 w-2 rounded-sm bg-app-secondary-500" />{{
|
|
389
398
|
t('reports.legend.metered')
|
|
@@ -404,9 +413,9 @@ watch(
|
|
|
404
413
|
<!-- Spend by model + by agent kind: the two axes a run has no single value for. -->
|
|
405
414
|
<div class="grid gap-6 md:grid-cols-2">
|
|
406
415
|
<section>
|
|
407
|
-
<h2 class="mb-2
|
|
416
|
+
<SectionLabel as="h2" class="mb-2">
|
|
408
417
|
{{ t('reports.spend.byModel') }}
|
|
409
|
-
</
|
|
418
|
+
</SectionLabel>
|
|
410
419
|
<ReportsSpendBreakdown
|
|
411
420
|
:rows="view.spend.byModel"
|
|
412
421
|
:currency="currency"
|
|
@@ -415,9 +424,9 @@ watch(
|
|
|
415
424
|
/>
|
|
416
425
|
</section>
|
|
417
426
|
<section>
|
|
418
|
-
<h2 class="mb-2
|
|
427
|
+
<SectionLabel as="h2" class="mb-2">
|
|
419
428
|
{{ t('reports.spend.byAgentKind') }}
|
|
420
|
-
</
|
|
429
|
+
</SectionLabel>
|
|
421
430
|
<ReportsSpendBreakdown
|
|
422
431
|
:rows="view.spend.byAgentKind"
|
|
423
432
|
:currency="currency"
|
|
@@ -434,9 +443,9 @@ watch(
|
|
|
434
443
|
breakdowns the projection caps, and each says so under its own card. -->
|
|
435
444
|
<div class="grid gap-6 md:grid-cols-2">
|
|
436
445
|
<section>
|
|
437
|
-
<h2 class="mb-2
|
|
446
|
+
<SectionLabel as="h2" class="mb-2">
|
|
438
447
|
{{ t('reports.spend.byTicket') }}
|
|
439
|
-
</
|
|
448
|
+
</SectionLabel>
|
|
440
449
|
<ReportsSpendBreakdown
|
|
441
450
|
:rows="view.spend.byTicket"
|
|
442
451
|
:currency="currency"
|
|
@@ -446,9 +455,9 @@ watch(
|
|
|
446
455
|
/>
|
|
447
456
|
</section>
|
|
448
457
|
<section>
|
|
449
|
-
<h2 class="mb-2
|
|
458
|
+
<SectionLabel as="h2" class="mb-2">
|
|
450
459
|
{{ t('reports.spend.byRun') }}
|
|
451
|
-
</
|
|
460
|
+
</SectionLabel>
|
|
452
461
|
<ReportsSpendBreakdown
|
|
453
462
|
:rows="view.spend.byRun"
|
|
454
463
|
:currency="currency"
|
|
@@ -462,29 +471,24 @@ watch(
|
|
|
462
471
|
<!-- The shared axis: spend AND activity for the same grouping, side by side. -->
|
|
463
472
|
<section class="flex flex-col gap-3">
|
|
464
473
|
<div class="flex flex-wrap items-center gap-2">
|
|
465
|
-
<
|
|
474
|
+
<SectionLabel as="h2">
|
|
466
475
|
{{ t('reports.breakdown.title') }}
|
|
467
|
-
</
|
|
468
|
-
<
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
@click="dimension = opt.value"
|
|
480
|
-
>
|
|
481
|
-
{{ opt.label }}
|
|
482
|
-
</button>
|
|
483
|
-
</div>
|
|
476
|
+
</SectionLabel>
|
|
477
|
+
<UTabs
|
|
478
|
+
:model-value="dimension"
|
|
479
|
+
:items="DIMENSIONS"
|
|
480
|
+
:content="false"
|
|
481
|
+
size="xs"
|
|
482
|
+
@update:model-value="dimension = $event as ReportActivityDimension"
|
|
483
|
+
>
|
|
484
|
+
<template #default="{ item }">
|
|
485
|
+
<span :data-testid="`reports-dimension-${item.value}`">{{ item.label }}</span>
|
|
486
|
+
</template>
|
|
487
|
+
</UTabs>
|
|
484
488
|
</div>
|
|
485
489
|
<div class="grid gap-6 md:grid-cols-2">
|
|
486
490
|
<div>
|
|
487
|
-
<h3 class="mb-2 text-
|
|
491
|
+
<h3 class="mb-2 text-2xs text-dimmed">
|
|
488
492
|
{{ t('reports.spend.heading') }}
|
|
489
493
|
</h3>
|
|
490
494
|
<ReportsSpendBreakdown
|
|
@@ -495,7 +499,7 @@ watch(
|
|
|
495
499
|
/>
|
|
496
500
|
</div>
|
|
497
501
|
<div>
|
|
498
|
-
<h3 class="mb-2 text-
|
|
502
|
+
<h3 class="mb-2 text-2xs text-dimmed">
|
|
499
503
|
{{ t('reports.activity.heading') }}
|
|
500
504
|
</h3>
|
|
501
505
|
<div class="rounded-lg border border-default bg-default/40 p-4">
|
|
@@ -532,7 +536,7 @@ watch(
|
|
|
532
536
|
</div>
|
|
533
537
|
<!-- The status counts in text: the reserved status hues are
|
|
534
538
|
red-green adjacent, so identity is never colour alone. -->
|
|
535
|
-
<p class="mt-1 flex flex-wrap gap-x-2 text-
|
|
539
|
+
<p class="mt-1 flex flex-wrap gap-x-2 text-3xs text-dimmed">
|
|
536
540
|
<span v-for="segment in activitySegments(row)" :key="segment.status">
|
|
537
541
|
{{ n(segment.count, 'decimal') }} {{ statusLabel(segment.status) }}
|
|
538
542
|
</span>
|
|
@@ -545,7 +549,7 @@ watch(
|
|
|
545
549
|
</p>
|
|
546
550
|
</li>
|
|
547
551
|
</ul>
|
|
548
|
-
<div class="mt-3 flex flex-wrap items-center gap-3 text-
|
|
552
|
+
<div class="mt-3 flex flex-wrap items-center gap-3 text-2xs text-dimmed">
|
|
549
553
|
<span
|
|
550
554
|
v-for="status in ['done', 'failed', 'running', 'other'] as const"
|
|
551
555
|
:key="status"
|
|
@@ -66,7 +66,7 @@ const max = computed(() => maxOf(props.rows, spendMagnitude))
|
|
|
66
66
|
:style="{ width: `${segmentPct(row.subscriptionCost, max)}%` }"
|
|
67
67
|
/>
|
|
68
68
|
</div>
|
|
69
|
-
<p class="mt-1 text-
|
|
69
|
+
<p class="mt-1 text-3xs text-dimmed">
|
|
70
70
|
{{ t('reports.spend.calls', { count: row.calls }, row.calls) }} ·
|
|
71
71
|
{{
|
|
72
72
|
t('reports.spend.tokens', {
|
|
@@ -77,7 +77,7 @@ const max = computed(() => maxOf(props.rows, spendMagnitude))
|
|
|
77
77
|
</p>
|
|
78
78
|
</li>
|
|
79
79
|
</ul>
|
|
80
|
-
<p v-if="cap" class="mt-3 text-
|
|
80
|
+
<p v-if="cap" class="mt-3 text-3xs text-dimmed" :data-testid="`${testId}-capped`">
|
|
81
81
|
{{
|
|
82
82
|
t('reports.spend.capped', { shown: n(cap.returned), omitted: n(cap.omitted) }, cap.omitted)
|
|
83
83
|
}}
|