@cat-factory/app 0.309.0 → 0.310.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -2
- package/app/components/assistant/AssistantModal.vue +5 -4
- package/app/components/auth/BackendMisconfiguredScreen.vue +4 -3
- package/app/components/auth/LoginScreen.vue +40 -26
- package/app/components/auth/ResetPasswordScreen.vue +9 -4
- package/app/components/auth/UserMenu.vue +4 -3
- package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +34 -23
- package/app/components/binaryOutput/StoredAssetView.vue +8 -6
- package/app/components/board/AddTaskModal.vue +16 -15
- package/app/components/board/AgentFailureCard.vue +12 -9
- package/app/components/board/AgentFailureHistory.vue +18 -9
- package/app/components/board/CreateInitiativeModal.vue +5 -4
- package/app/components/board/FailureDetail.vue +22 -12
- package/app/components/board/ReviewFrictionDialog.vue +4 -3
- package/app/components/board/nodes/BlockNode.vue +17 -15
- package/app/components/board/nodes/DecisionBadge.vue +4 -3
- package/app/components/board/nodes/FrameSwimlanes.vue +4 -3
- package/app/components/board/nodes/TaskCard.vue +12 -7
- package/app/components/board/nodes/TaskPipelineMini.vue +9 -7
- package/app/components/bootstrap/AdoptionReviewModal.vue +30 -21
- package/app/components/bootstrap/BootstrapModal.vue +3 -3
- package/app/components/brainstorm/BrainstormWindow.vue +5 -3
- package/app/components/bugFishing/BugFishingWindow.vue +49 -27
- package/app/components/clarity/ClarityReviewWindow.vue +5 -3
- package/app/components/common/CopyButton.vue +12 -11
- package/app/components/common/IconButton.vue +34 -9
- package/app/components/context/ContextAttachmentFields.vue +23 -12
- package/app/components/documents/ContextDocumentPicker.vue +12 -9
- package/app/components/documents/DocumentImportModal.vue +4 -3
- package/app/components/documents/DocumentOriginLink.vue +12 -9
- package/app/components/documents/DocumentSyncState.vue +3 -3
- package/app/components/documents/RepoContextDocPicker.vue +4 -3
- package/app/components/environments/EnvironmentStatusPanel.vue +4 -3
- package/app/components/followUp/FollowUpWindow.vue +9 -6
- package/app/components/forkDecision/ForkDecisionWindow.vue +71 -80
- package/app/components/foundational/FoundationalServiceCatalogList.vue +3 -2
- package/app/components/foundational/FoundationalServiceRegistry.vue +7 -6
- package/app/components/foundational/FoundationalServiceSources.vue +7 -6
- package/app/components/fragments/FragmentLibraryManager.vue +5 -4
- package/app/components/fragments/FragmentSelector.vue +12 -9
- package/app/components/gates/GateFailingCheckList.vue +4 -3
- package/app/components/gates/GateResultView.vue +17 -12
- package/app/components/github/AddServiceFromRepoModal.vue +11 -7
- package/app/components/github/GitHubOnboarding.vue +7 -2
- package/app/components/github/GitHubPanel.vue +9 -6
- package/app/components/github/RepoTreeBrowser.vue +15 -12
- package/app/components/humanTest/HumanTestWindow.vue +13 -9
- package/app/components/initiative/InitiativePlanReview.vue +28 -18
- package/app/components/initiative/InitiativeTrackerWindow.vue +171 -124
- package/app/components/judge/JudgeResultView.vue +5 -3
- package/app/components/kaizen/KaizenPanel.vue +67 -53
- package/app/components/layout/AccountTeamSettings.vue +9 -9
- package/app/components/layout/AppearanceSwitcher.vue +4 -3
- package/app/components/layout/BoardSwitcher.vue +10 -8
- package/app/components/layout/BoardToolbar.vue +5 -4
- package/app/components/layout/CommandBar.vue +4 -3
- package/app/components/layout/DefaultTestEnvBanner.vue +4 -3
- package/app/components/layout/IntegrationsHub.vue +8 -6
- package/app/components/layout/LanguageSwitcher.vue +4 -3
- package/app/components/layout/ModelProvidersHub.vue +4 -3
- package/app/components/layout/NotificationsInbox.vue +40 -30
- package/app/components/layout/PersonalSetupModal.vue +4 -3
- package/app/components/layout/RolePrompt.vue +4 -3
- package/app/components/layout/SideBar.vue +4 -3
- package/app/components/layout/TranslationWarningBanner.vue +4 -3
- package/app/components/layout/UiModeSwitcher.vue +8 -6
- package/app/components/layout/UiRoleSwitcher.vue +8 -6
- package/app/components/layout/WorkspaceMembersSettings.vue +2 -2
- package/app/components/media/ArtifactLightbox.vue +69 -39
- package/app/components/media/ImageCompare.vue +69 -74
- package/app/components/observability/OutcomeFilterChips.vue +5 -4
- package/app/components/observability/RunFailureSummary.vue +8 -6
- package/app/components/observability/StepModelActivity.vue +5 -3
- package/app/components/observability/ToolCallList.vue +4 -2
- package/app/components/outcome/OutcomeSummaryWindow.vue +5 -4
- package/app/components/palettes/AgentPalette.vue +18 -14
- package/app/components/panels/AgentStepDetail.vue +30 -19
- package/app/components/panels/ObservabilityPanel.vue +149 -114
- package/app/components/panels/OperatorDashboardPanel.vue +99 -91
- package/app/components/panels/ReportsPanel.vue +64 -61
- package/app/components/panels/ResultWindowShell.vue +148 -134
- package/app/components/panels/StepContainerStatus.vue +9 -9
- package/app/components/panels/StepDelegatedStatus.vue +11 -9
- package/app/components/panels/StepRestartControl.vue +3 -2
- package/app/components/panels/inspector/EpicChildren.vue +4 -3
- package/app/components/panels/inspector/FrontendConfig.vue +3 -2
- package/app/components/panels/inspector/InspectorSection.vue +22 -17
- package/app/components/panels/inspector/ServiceConnections.vue +3 -2
- package/app/components/panels/inspector/ServiceTestConfig.vue +5 -4
- package/app/components/panels/inspector/TaskExecution.vue +5 -4
- package/app/components/panels/inspector/TaskRunSettings.vue +10 -6
- package/app/components/pipeline/EstimateThresholdFields.vue +13 -10
- package/app/components/pipeline/GateConfigFields.vue +14 -18
- package/app/components/pipeline/PipelineBuilder.vue +90 -77
- package/app/components/pipeline/PipelinePicker.vue +8 -6
- package/app/components/pipeline/PipelineProgress.vue +26 -21
- package/app/components/prReview/PrReviewWindow.vue +46 -25
- package/app/components/providers/ApiKeysSection.vue +4 -3
- package/app/components/ralph/RalphLoopResultView.vue +4 -3
- package/app/components/requirements/RequirementsReviewWindow.vue +10 -6
- package/app/components/riskPolicy/RiskPolicyPicker.vue +8 -6
- package/app/components/sandbox/SandboxPanel.vue +73 -54
- package/app/components/settings/CloudflareHandlerSection.vue +33 -30
- package/app/components/settings/ConsensusGroupsSection.vue +40 -30
- package/app/components/settings/InfraHandlersConfigurator.vue +16 -13
- package/app/components/settings/InfrastructureBackendPicker.vue +17 -17
- package/app/components/settings/IssueTrackerPanel.vue +21 -6
- package/app/components/settings/LocalModelEndpointsPanel.vue +3 -2
- package/app/components/settings/ModelConfigurationPanel.vue +9 -8
- package/app/components/settings/OpenRouterCatalogPanel.vue +4 -3
- package/app/components/settings/ProviderPreferenceEditor.vue +5 -6
- package/app/components/settings/RiskPolicyEditorRow.vue +3 -2
- package/app/components/settings/ServiceFragmentDefaultsPanel.vue +10 -8
- package/app/components/skills/ReviewSkillQueue.vue +4 -3
- package/app/components/skills/SkillLibraryManager.vue +7 -6
- package/app/components/slack/SlackPanel.vue +9 -5
- package/app/components/spec/ServiceSpecWindow.vue +4 -3
- package/app/components/tasks/ContextIssuePicker.vue +12 -9
- package/app/components/tasks/TaskContextIssues.vue +4 -3
- package/app/components/testing/TestReportWindow.vue +14 -8
- package/app/components/theme/ThemeImportModal.vue +2 -2
- package/app/components/visualConfirm/VisualConfirmationWindow.vue +62 -35
- package/i18n/locales/de.json +7 -3
- package/i18n/locales/en.json +7 -3
- package/i18n/locales/es.json +7 -3
- package/i18n/locales/fr.json +7 -3
- package/i18n/locales/he.json +7 -3
- package/i18n/locales/it.json +7 -3
- package/i18n/locales/ja.json +7 -3
- package/i18n/locales/pl.json +7 -3
- package/i18n/locales/tr.json +7 -3
- package/i18n/locales/uk.json +7 -3
- package/package.json +1 -1
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import { computed, ref, watch } from 'vue'
|
|
10
10
|
import { useModalBehavior } from '@modular-vue/core'
|
|
11
11
|
import type { ArtifactBlobs } from '~/composables/useArtifactBlobs'
|
|
12
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
12
13
|
|
|
13
14
|
interface LightboxItem {
|
|
14
15
|
artifactId: string
|
|
@@ -180,39 +181,56 @@ onBeforeUnmount(() => window.removeEventListener('keydown', onKey, true))
|
|
|
180
181
|
{{ t('media.lightbox.counter', { current: index + 1, total }) }}
|
|
181
182
|
</span>
|
|
182
183
|
<div class="flex shrink-0 items-center gap-1">
|
|
183
|
-
<
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
<IconButton
|
|
185
|
+
color="neutral"
|
|
186
|
+
variant="ghost"
|
|
187
|
+
icon="i-lucide-zoom-out"
|
|
188
|
+
:label="t('media.lightbox.zoomOut')"
|
|
189
|
+
:ui="{
|
|
190
|
+
base: 'rounded-md p-1.5 text-muted hover:bg-elevated hover:text-default disabled:opacity-40',
|
|
191
|
+
leadingIcon: 'h-4 w-4',
|
|
192
|
+
}"
|
|
186
193
|
:disabled="scale <= MIN_SCALE"
|
|
187
194
|
@click="zoomBy(1 / 1.25)"
|
|
188
|
-
|
|
189
|
-
<UIcon name="i-lucide-zoom-out" class="h-4 w-4" />
|
|
190
|
-
</button>
|
|
195
|
+
/>
|
|
191
196
|
<span class="w-10 text-center text-2xs tabular-nums text-dimmed">{{
|
|
192
197
|
n(scale, 'percent')
|
|
193
198
|
}}</span>
|
|
194
|
-
<
|
|
195
|
-
|
|
196
|
-
|
|
199
|
+
<IconButton
|
|
200
|
+
color="neutral"
|
|
201
|
+
variant="ghost"
|
|
202
|
+
icon="i-lucide-zoom-in"
|
|
203
|
+
:label="t('media.lightbox.zoomIn')"
|
|
204
|
+
:ui="{
|
|
205
|
+
base: 'rounded-md p-1.5 text-muted hover:bg-elevated hover:text-default disabled:opacity-40',
|
|
206
|
+
leadingIcon: 'h-4 w-4',
|
|
207
|
+
}"
|
|
197
208
|
:disabled="scale >= MAX_SCALE"
|
|
198
209
|
@click="zoomBy(1.25)"
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
:
|
|
210
|
+
/>
|
|
211
|
+
<IconButton
|
|
212
|
+
color="neutral"
|
|
213
|
+
variant="ghost"
|
|
214
|
+
icon="i-lucide-maximize"
|
|
215
|
+
:label="t('media.lightbox.reset')"
|
|
216
|
+
:ui="{
|
|
217
|
+
base: 'rounded-md p-1.5 text-muted hover:bg-elevated hover:text-default',
|
|
218
|
+
leadingIcon: 'h-4 w-4',
|
|
219
|
+
}"
|
|
205
220
|
@click="resetView"
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
221
|
+
/>
|
|
222
|
+
<IconButton
|
|
223
|
+
color="neutral"
|
|
224
|
+
variant="ghost"
|
|
225
|
+
icon="i-lucide-x"
|
|
226
|
+
class="ms-1"
|
|
227
|
+
:label="t('media.lightbox.close')"
|
|
228
|
+
:ui="{
|
|
229
|
+
base: 'rounded-md p-1.5 text-muted hover:bg-elevated hover:text-default',
|
|
230
|
+
leadingIcon: 'h-4 w-4',
|
|
231
|
+
}"
|
|
212
232
|
@click="close"
|
|
213
|
-
|
|
214
|
-
<UIcon name="i-lucide-x" class="h-4 w-4" />
|
|
215
|
-
</button>
|
|
233
|
+
/>
|
|
216
234
|
</div>
|
|
217
235
|
</div>
|
|
218
236
|
|
|
@@ -222,14 +240,19 @@ onBeforeUnmount(() => window.removeEventListener('keydown', onKey, true))
|
|
|
222
240
|
@wheel="onWheel"
|
|
223
241
|
@click.self="close"
|
|
224
242
|
>
|
|
225
|
-
<
|
|
243
|
+
<IconButton
|
|
226
244
|
v-if="total > 1"
|
|
227
|
-
|
|
228
|
-
|
|
245
|
+
color="neutral"
|
|
246
|
+
variant="ghost"
|
|
247
|
+
icon="i-lucide-chevron-left"
|
|
248
|
+
class="absolute start-3 top-1/2 z-10 -translate-y-1/2"
|
|
249
|
+
:label="t('media.lightbox.prev')"
|
|
250
|
+
:ui="{
|
|
251
|
+
base: 'rounded-full bg-default/80 p-2 text-toned hover:bg-elevated hover:text-highlighted',
|
|
252
|
+
leadingIcon: 'h-5 w-5 rtl:-scale-x-100',
|
|
253
|
+
}"
|
|
229
254
|
@click="go(-1)"
|
|
230
|
-
|
|
231
|
-
<UIcon name="i-lucide-chevron-left" class="h-5 w-5 rtl:-scale-x-100" />
|
|
232
|
-
</button>
|
|
255
|
+
/>
|
|
233
256
|
|
|
234
257
|
<img
|
|
235
258
|
v-if="url"
|
|
@@ -257,23 +280,30 @@ onBeforeUnmount(() => window.removeEventListener('keydown', onKey, true))
|
|
|
257
280
|
<p class="text-xs">
|
|
258
281
|
{{ state === 'error' ? t('media.lightbox.failed') : t('media.lightbox.loading') }}
|
|
259
282
|
</p>
|
|
260
|
-
<
|
|
283
|
+
<UButton
|
|
284
|
+
color="neutral"
|
|
285
|
+
variant="link"
|
|
261
286
|
v-if="state === 'error' && current"
|
|
262
|
-
class="text-xs text-app-warning-300 hover:underline"
|
|
287
|
+
class="p-0 text-xs text-app-warning-300 hover:underline"
|
|
263
288
|
@click="props.blobs.retry(current.artifactId)"
|
|
264
289
|
>
|
|
265
290
|
{{ t('common.retry') }}
|
|
266
|
-
</
|
|
291
|
+
</UButton>
|
|
267
292
|
</div>
|
|
268
293
|
|
|
269
|
-
<
|
|
294
|
+
<IconButton
|
|
270
295
|
v-if="total > 1"
|
|
271
|
-
|
|
272
|
-
|
|
296
|
+
color="neutral"
|
|
297
|
+
variant="ghost"
|
|
298
|
+
icon="i-lucide-chevron-right"
|
|
299
|
+
class="absolute end-3 top-1/2 z-10 -translate-y-1/2"
|
|
300
|
+
:label="t('media.lightbox.next')"
|
|
301
|
+
:ui="{
|
|
302
|
+
base: 'rounded-full bg-default/80 p-2 text-toned hover:bg-elevated hover:text-highlighted',
|
|
303
|
+
leadingIcon: 'h-5 w-5 rtl:-scale-x-100',
|
|
304
|
+
}"
|
|
273
305
|
@click="go(1)"
|
|
274
|
-
|
|
275
|
-
<UIcon name="i-lucide-chevron-right" class="h-5 w-5 rtl:-scale-x-100" />
|
|
276
|
-
</button>
|
|
306
|
+
/>
|
|
277
307
|
</div>
|
|
278
308
|
</div>
|
|
279
309
|
</Teleport>
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
// as a drag-and-drop / click upload target (emits `uploadReference`).
|
|
10
10
|
import { computed, nextTick, ref, watch } from 'vue'
|
|
11
11
|
import type { ArtifactBlobs } from '~/composables/useArtifactBlobs'
|
|
12
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
12
13
|
|
|
13
14
|
const props = defineProps<{
|
|
14
15
|
view: string
|
|
@@ -135,23 +136,18 @@ async function renderDiff() {
|
|
|
135
136
|
watch([mode, actualUrl, refUrl], renderDiff, { immediate: true })
|
|
136
137
|
|
|
137
138
|
// --- reference upload (drag-drop + click) ---
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
//
|
|
141
|
-
// can't slip past the picker's `accept` filter.
|
|
139
|
+
// `UFileUpload` owns the picker, the drop zone and the drag state; the click-to-replace
|
|
140
|
+
// affordance calls its `open()`. The type guard stays ours: `accept` filters the PICKER, and a
|
|
141
|
+
// dropped GIF/SVG/WebP would otherwise arrive anyway.
|
|
142
142
|
const ACCEPTED = /^image\/(png|jpeg)$/
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
const pendingRef = ref<File | null>(null)
|
|
144
|
+
watch(pendingRef, (file) => {
|
|
145
145
|
if (file && ACCEPTED.test(file.type)) emit('uploadReference', file)
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
151
|
-
function onRefInput(e: Event) {
|
|
152
|
-
pickFile((e.target as HTMLInputElement).files)
|
|
153
|
-
if (refInput.value) refInput.value.value = ''
|
|
154
|
-
}
|
|
146
|
+
// Cleared either way, so a fresh pick is a fresh file. `UFileUpload` carries `reset` for the
|
|
147
|
+
// other half of this: clearing the model alone leaves the native input holding the file it
|
|
148
|
+
// already has, and the browser fires no change event when the same one is chosen twice.
|
|
149
|
+
if (file) pendingRef.value = null
|
|
150
|
+
})
|
|
155
151
|
</script>
|
|
156
152
|
|
|
157
153
|
<template>
|
|
@@ -163,16 +159,23 @@ function onRefInput(e: Event) {
|
|
|
163
159
|
v-if="MODES.length > 1"
|
|
164
160
|
class="flex items-center gap-0.5 rounded-md border border-default bg-app-950/60 p-0.5"
|
|
165
161
|
>
|
|
166
|
-
<
|
|
162
|
+
<IconButton
|
|
167
163
|
v-for="m in MODES"
|
|
168
164
|
:key="m.id"
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
:
|
|
165
|
+
color="neutral"
|
|
166
|
+
variant="ghost"
|
|
167
|
+
:icon="m.icon"
|
|
168
|
+
:label="m.label"
|
|
169
|
+
:aria-pressed="mode === m.id"
|
|
170
|
+
:ui="{
|
|
171
|
+
base: [
|
|
172
|
+
'rounded-sm px-1.5 py-1 text-muted hover:bg-transparent hover:text-default',
|
|
173
|
+
mode === m.id ? 'bg-elevated text-app-100' : '',
|
|
174
|
+
].join(' '),
|
|
175
|
+
leadingIcon: 'h-3.5 w-3.5',
|
|
176
|
+
}"
|
|
172
177
|
@click="mode = m.id"
|
|
173
|
-
|
|
174
|
-
<UIcon :name="m.icon" class="h-3.5 w-3.5" />
|
|
175
|
-
</button>
|
|
178
|
+
/>
|
|
176
179
|
</div>
|
|
177
180
|
</div>
|
|
178
181
|
|
|
@@ -182,9 +185,11 @@ function onRefInput(e: Event) {
|
|
|
182
185
|
<figcaption class="text-3xs uppercase tracking-wide text-dimmed">
|
|
183
186
|
{{ t('media.compare.actual') }}
|
|
184
187
|
</figcaption>
|
|
185
|
-
<
|
|
188
|
+
<UButton
|
|
186
189
|
v-if="actualUrl"
|
|
187
|
-
|
|
190
|
+
color="neutral"
|
|
191
|
+
variant="ghost"
|
|
192
|
+
class="block w-full overflow-hidden rounded-sm border border-default p-0 hover:border-app-600 hover:bg-transparent"
|
|
188
193
|
@click="actualId && emit('expand', actualId)"
|
|
189
194
|
>
|
|
190
195
|
<img
|
|
@@ -192,7 +197,7 @@ function onRefInput(e: Event) {
|
|
|
192
197
|
:alt="t('media.compare.actualAlt', { view })"
|
|
193
198
|
class="w-full cursor-zoom-in"
|
|
194
199
|
/>
|
|
195
|
-
</
|
|
200
|
+
</UButton>
|
|
196
201
|
<div
|
|
197
202
|
v-else
|
|
198
203
|
class="flex h-32 items-center justify-center rounded-sm border border-dashed border-muted text-2xs text-app-600"
|
|
@@ -214,40 +219,39 @@ function onRefInput(e: Event) {
|
|
|
214
219
|
{{ t('media.compare.fromLinkedDesign') }}
|
|
215
220
|
</span>
|
|
216
221
|
</figcaption>
|
|
217
|
-
<
|
|
218
|
-
v-
|
|
219
|
-
|
|
220
|
-
|
|
222
|
+
<UFileUpload
|
|
223
|
+
v-model="pendingRef"
|
|
224
|
+
reset
|
|
225
|
+
accept="image/png,image/jpeg"
|
|
226
|
+
:disabled="busy"
|
|
227
|
+
:preview="false"
|
|
228
|
+
:label="t('media.compare.dropHint')"
|
|
229
|
+
icon="i-lucide-image-up"
|
|
230
|
+
:ui="{ base: 'h-32 text-2xs' }"
|
|
221
231
|
>
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
@dragleave.prevent="dragOver = false"
|
|
246
|
-
@drop.prevent="onDrop"
|
|
247
|
-
>
|
|
248
|
-
<UIcon name="i-lucide-image-up" class="h-5 w-5" />
|
|
249
|
-
<span>{{ t('media.compare.dropHint') }}</span>
|
|
250
|
-
</div>
|
|
232
|
+
<!-- With a reference already in place the tile IS the surface: it opens the lightbox,
|
|
233
|
+
and the hover affordance opens the picker the same drop zone would. -->
|
|
234
|
+
<template v-if="refUrl" #default="{ open }">
|
|
235
|
+
<UButton
|
|
236
|
+
variant="ghost"
|
|
237
|
+
color="neutral"
|
|
238
|
+
class="group relative block w-full overflow-hidden rounded-sm border border-default p-0 hover:border-app-600 hover:bg-transparent"
|
|
239
|
+
@click="referenceId && emit('expand', referenceId)"
|
|
240
|
+
>
|
|
241
|
+
<img
|
|
242
|
+
:src="refUrl"
|
|
243
|
+
:alt="t('media.compare.referenceAlt', { view })"
|
|
244
|
+
class="w-full cursor-zoom-in"
|
|
245
|
+
/>
|
|
246
|
+
<span
|
|
247
|
+
class="absolute bottom-1 end-1 rounded-sm bg-app-950/80 px-1.5 py-0.5 text-3xs text-toned opacity-0 group-hover:opacity-100"
|
|
248
|
+
@click.stop="open()"
|
|
249
|
+
>
|
|
250
|
+
{{ t('media.compare.replace') }}
|
|
251
|
+
</span>
|
|
252
|
+
</UButton>
|
|
253
|
+
</template>
|
|
254
|
+
</UFileUpload>
|
|
251
255
|
</figure>
|
|
252
256
|
</div>
|
|
253
257
|
|
|
@@ -265,12 +269,13 @@ function onRefInput(e: Event) {
|
|
|
265
269
|
</div>
|
|
266
270
|
<div class="flex items-center gap-2 text-2xs uppercase tracking-wide text-muted">
|
|
267
271
|
<span>{{ t('media.compare.reference') }}</span>
|
|
268
|
-
<
|
|
269
|
-
v-model
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
272
|
+
<USlider
|
|
273
|
+
v-model="overlayOpacity"
|
|
274
|
+
:min="0"
|
|
275
|
+
:max="100"
|
|
276
|
+
color="warning"
|
|
277
|
+
size="xs"
|
|
278
|
+
class="flex-1"
|
|
274
279
|
/>
|
|
275
280
|
<span>{{ t('media.compare.actual') }}</span>
|
|
276
281
|
</div>
|
|
@@ -326,15 +331,5 @@ function onRefInput(e: Event) {
|
|
|
326
331
|
<canvas ref="diffCanvas" :class="DIFF_CANVAS_CLASS" />
|
|
327
332
|
<p class="text-3xs text-dimmed">{{ t('media.compare.diffHint') }}</p>
|
|
328
333
|
</div>
|
|
329
|
-
|
|
330
|
-
<!-- Hidden file input shared by replace/drop zone -->
|
|
331
|
-
<input
|
|
332
|
-
ref="refInput"
|
|
333
|
-
type="file"
|
|
334
|
-
accept="image/png,image/jpeg"
|
|
335
|
-
class="hidden"
|
|
336
|
-
:disabled="busy"
|
|
337
|
-
@change="onRefInput"
|
|
338
|
-
/>
|
|
339
334
|
</div>
|
|
340
335
|
</template>
|
|
@@ -25,17 +25,18 @@ function toneClass(option: (typeof props.options)[number], active: boolean): str
|
|
|
25
25
|
|
|
26
26
|
<template>
|
|
27
27
|
<div class="flex rounded-lg border border-default p-0.5 text-xs">
|
|
28
|
-
<
|
|
28
|
+
<UButton
|
|
29
|
+
color="neutral"
|
|
30
|
+
variant="ghost"
|
|
29
31
|
v-for="option in options"
|
|
30
32
|
:key="option.value"
|
|
31
|
-
|
|
32
|
-
class="rounded-md px-2.5 py-1 transition"
|
|
33
|
+
class="rounded-md px-2.5 py-1 text-xs transition"
|
|
33
34
|
:class="toneClass(option, option.value === modelValue)"
|
|
34
35
|
:aria-pressed="option.value === modelValue"
|
|
35
36
|
@click="emit('update:modelValue', option.value)"
|
|
36
37
|
>
|
|
37
38
|
{{ option.label }}
|
|
38
39
|
<span class="tabular-nums opacity-70">{{ option.count }}</span>
|
|
39
|
-
</
|
|
40
|
+
</UButton>
|
|
40
41
|
</div>
|
|
41
42
|
</template>
|
|
@@ -121,9 +121,10 @@ const earlierFailedToolCalls = computed(() =>
|
|
|
121
121
|
<!-- The failing calls themselves. -->
|
|
122
122
|
<div class="mt-3 space-y-2">
|
|
123
123
|
<!-- Last model call that FAILED outright. -->
|
|
124
|
-
<
|
|
124
|
+
<UButton
|
|
125
|
+
color="neutral"
|
|
126
|
+
variant="ghost"
|
|
125
127
|
v-if="evidence.lastErroredCall"
|
|
126
|
-
type="button"
|
|
127
128
|
class="flex w-full items-start gap-3 rounded-lg border border-app-error-900/50 bg-app-950/50 px-3 py-2 text-start transition hover:bg-default/70"
|
|
128
129
|
@click="emit('showCall', evidence.lastErroredCall.id)"
|
|
129
130
|
>
|
|
@@ -159,12 +160,13 @@ const earlierFailedToolCalls = computed(() =>
|
|
|
159
160
|
</p>
|
|
160
161
|
</div>
|
|
161
162
|
<UIcon name="i-lucide-chevron-right" class="mt-0.5 h-4 w-4 shrink-0 text-app-600" />
|
|
162
|
-
</
|
|
163
|
+
</UButton>
|
|
163
164
|
|
|
164
165
|
<!-- Last TOOL call that failed: the row no rollup counts. -->
|
|
165
|
-
<
|
|
166
|
+
<UButton
|
|
167
|
+
color="neutral"
|
|
168
|
+
variant="ghost"
|
|
166
169
|
v-if="evidence.lastFailedToolCall"
|
|
167
|
-
type="button"
|
|
168
170
|
class="flex w-full items-start gap-3 rounded-lg border border-app-error-900/50 bg-app-950/50 px-3 py-2 text-start transition hover:bg-default/70"
|
|
169
171
|
@click="emit('showFailingTools')"
|
|
170
172
|
>
|
|
@@ -208,7 +210,7 @@ const earlierFailedToolCalls = computed(() =>
|
|
|
208
210
|
</p>
|
|
209
211
|
</div>
|
|
210
212
|
<UIcon name="i-lucide-chevron-right" class="mt-0.5 h-4 w-4 shrink-0 text-app-600" />
|
|
211
|
-
</
|
|
213
|
+
</UButton>
|
|
212
214
|
|
|
213
215
|
<!-- Nothing failing to point at. Which of the reasons it is decides what an operator should
|
|
214
216
|
do next, so each gets its own sentence rather than one shared shrug. `emptyReason` is
|
|
@@ -35,13 +35,15 @@ function openObservability() {
|
|
|
35
35
|
<SectionLabel as="span">
|
|
36
36
|
{{ t('observability.modelActivity') }}
|
|
37
37
|
</SectionLabel>
|
|
38
|
-
<
|
|
38
|
+
<UButton
|
|
39
|
+
color="neutral"
|
|
40
|
+
variant="ghost"
|
|
39
41
|
v-if="instanceId"
|
|
40
|
-
class="text-2xs text-app-info-400 hover:text-app-info-300"
|
|
42
|
+
class="p-0 text-2xs text-app-info-400 hover:bg-transparent hover:text-app-info-300"
|
|
41
43
|
@click="openObservability"
|
|
42
44
|
>
|
|
43
45
|
{{ t('observability.viewAllCalls') }}
|
|
44
|
-
</
|
|
46
|
+
</UButton>
|
|
45
47
|
</div>
|
|
46
48
|
<StepMetricsBar
|
|
47
49
|
v-if="hasCalls && metrics"
|
|
@@ -211,7 +211,9 @@ function prettyArgs(raw: string): string {
|
|
|
211
211
|
class="overflow-hidden rounded-xl border border-default bg-default/40"
|
|
212
212
|
:class="!call.ok ? 'border-app-error-900/60' : ''"
|
|
213
213
|
>
|
|
214
|
-
<
|
|
214
|
+
<UButton
|
|
215
|
+
color="neutral"
|
|
216
|
+
variant="ghost"
|
|
215
217
|
class="flex w-full items-center gap-3 px-4 py-2.5 text-start transition hover:bg-default/70"
|
|
216
218
|
@click="toggle(call)"
|
|
217
219
|
>
|
|
@@ -236,7 +238,7 @@ function prettyArgs(raw: string): string {
|
|
|
236
238
|
</UBadge>
|
|
237
239
|
<span class="hidden text-app-600 md:inline">{{ clock(call.startedAt) }}</span>
|
|
238
240
|
</div>
|
|
239
|
-
</
|
|
241
|
+
</UButton>
|
|
240
242
|
|
|
241
243
|
<div v-if="expanded[call.id]" class="border-t border-default px-4 py-3 space-y-3">
|
|
242
244
|
<div class="flex flex-wrap gap-x-5 gap-y-1 text-2xs text-dimmed">
|
|
@@ -693,11 +693,12 @@ function openTestReport() {
|
|
|
693
693
|
}}
|
|
694
694
|
</p>
|
|
695
695
|
<div class="grid grid-cols-2 gap-2 sm:grid-cols-3">
|
|
696
|
-
<
|
|
696
|
+
<UButton
|
|
697
|
+
color="neutral"
|
|
698
|
+
variant="ghost"
|
|
697
699
|
v-for="(view, position) in outcome.visuals.views"
|
|
698
700
|
:key="`${position}:${view.view}`"
|
|
699
|
-
|
|
700
|
-
class="group overflow-hidden rounded-md border border-default bg-app-950/60 text-start transition hover:border-app-600"
|
|
701
|
+
class="group block overflow-hidden rounded-md border border-default bg-app-950/60 hover:bg-app-950/60 focus-visible:bg-app-950/60 disabled:bg-app-950/60 p-0 text-start transition hover:border-app-600"
|
|
701
702
|
:disabled="!view.artifactId"
|
|
702
703
|
data-testid="outcome-shot"
|
|
703
704
|
@click="openShot(view, position)"
|
|
@@ -730,7 +731,7 @@ function openTestReport() {
|
|
|
730
731
|
/>
|
|
731
732
|
{{ view.view }}
|
|
732
733
|
</span>
|
|
733
|
-
</
|
|
734
|
+
</UButton>
|
|
734
735
|
</div>
|
|
735
736
|
</template>
|
|
736
737
|
<template v-else>
|
|
@@ -74,24 +74,28 @@ function toggle(id: string) {
|
|
|
74
74
|
</div>
|
|
75
75
|
<div class="space-y-2">
|
|
76
76
|
<section v-for="g in groups" :key="g.id">
|
|
77
|
-
<
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
class="
|
|
77
|
+
<UButton
|
|
78
|
+
color="neutral"
|
|
79
|
+
variant="link"
|
|
80
|
+
class="group w-full rounded-sm px-1 py-1"
|
|
81
|
+
:aria-expanded="!isCollapsed(g.id)"
|
|
81
82
|
@click="toggle(g.id)"
|
|
82
83
|
>
|
|
83
|
-
<
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
84
|
+
<SectionLabel as="span" class="flex w-full items-center gap-1.5 group-hover:text-default">
|
|
85
|
+
<UIcon
|
|
86
|
+
:name="isCollapsed(g.id) ? 'i-lucide-chevron-right' : 'i-lucide-chevron-down'"
|
|
87
|
+
class="h-3.5 w-3.5 shrink-0"
|
|
88
|
+
/>
|
|
89
|
+
<span>{{ g.label }}</span>
|
|
90
|
+
<span class="ms-auto text-app-600">{{ g.agents.length }}</span>
|
|
91
|
+
</SectionLabel>
|
|
92
|
+
</UButton>
|
|
90
93
|
<div v-if="!isCollapsed(g.id)" class="mt-1 space-y-1.5">
|
|
91
|
-
<
|
|
94
|
+
<UButton
|
|
95
|
+
color="neutral"
|
|
96
|
+
variant="ghost"
|
|
92
97
|
v-for="a in g.agents"
|
|
93
98
|
:key="a.kind"
|
|
94
|
-
type="button"
|
|
95
99
|
class="flex w-full items-center gap-2.5 rounded-lg border border-muted bg-elevated/60 p-2 text-start transition hover:border-app-500 hover:bg-elevated"
|
|
96
100
|
:title="a.description"
|
|
97
101
|
:data-testid="`palette-agent-${a.kind}`"
|
|
@@ -108,7 +112,7 @@ function toggle(id: string) {
|
|
|
108
112
|
<div class="truncate text-3xs text-muted">{{ a.description }}</div>
|
|
109
113
|
</div>
|
|
110
114
|
<UIcon name="i-lucide-plus" class="ms-auto h-4 w-4 shrink-0 text-dimmed" />
|
|
111
|
-
</
|
|
115
|
+
</UButton>
|
|
112
116
|
</div>
|
|
113
117
|
</section>
|
|
114
118
|
</div>
|