@cat-factory/app 0.54.4 → 0.56.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/app/app.vue +14 -0
- package/app/components/auth/UserMenu.vue +1 -1
- package/app/components/board/AddTaskModal.vue +5 -4
- package/app/components/board/nodes/AgentChip.vue +2 -2
- package/app/components/board/nodes/BlockNode.vue +12 -8
- package/app/components/board/nodes/DraggableTask.vue +1 -1
- package/app/components/board/nodes/EpicNode.vue +1 -1
- package/app/components/board/nodes/ModuleFrame.vue +7 -4
- package/app/components/board/nodes/TaskCard.vue +2 -2
- package/app/components/board/nodes/TaskPipelineMini.vue +3 -3
- package/app/components/brainstorm/BrainstormWindow.vue +8 -7
- package/app/components/clarity/ClarityReviewWindow.vue +8 -7
- package/app/components/consensus/ConsensusSessionWindow.vue +2 -2
- package/app/components/documents/ContextDocumentPicker.vue +4 -4
- package/app/components/documents/SpawnPreviewModal.vue +4 -4
- package/app/components/focus/BlockFocusView.vue +11 -4
- package/app/components/fragments/FragmentLibraryManager.vue +5 -5
- package/app/components/gates/GateResultView.vue +3 -3
- package/app/components/github/GitHubPanel.vue +5 -2
- package/app/components/humanTest/HumanTestWindow.vue +1 -1
- package/app/components/kaizen/KaizenPanel.vue +5 -5
- package/app/components/kaizen/KaizenStepStatus.vue +2 -2
- package/app/components/layout/AccountDeploymentSettings.vue +31 -2
- package/app/components/layout/BoardSwitcher.vue +4 -4
- package/app/components/layout/CommandBar.vue +1 -1
- package/app/components/layout/IntegrationBackTitle.vue +2 -1
- package/app/components/layout/IntegrationsHub.vue +10 -4
- package/app/components/layout/LanguageSwitcher.vue +1 -1
- package/app/components/layout/NotificationsInbox.vue +1 -1
- package/app/components/layout/PersonalSetupModal.vue +5 -2
- package/app/components/layout/SideBar.vue +5 -3
- package/app/components/media/ArtifactLightbox.vue +5 -5
- package/app/components/media/ImageCompare.vue +6 -1
- package/app/components/observability/StepMetricsBar.vue +6 -2
- package/app/components/palettes/AgentPalette.vue +4 -4
- package/app/components/panels/AgentStepDetail.vue +12 -12
- package/app/components/panels/GenericStructuredResultView.vue +1 -1
- package/app/components/panels/InspectorPanel.vue +2 -2
- package/app/components/panels/ObservabilityPanel.vue +6 -6
- package/app/components/panels/StepMetadataCard.vue +1 -1
- package/app/components/panels/inspector/ContainerSummary.vue +2 -2
- package/app/components/panels/inspector/EpicChildren.vue +3 -3
- package/app/components/panels/inspector/RecurringScheduleSettings.vue +1 -1
- package/app/components/panels/inspector/ServiceFragments.vue +1 -1
- package/app/components/panels/inspector/ServiceTestConfig.vue +1 -1
- package/app/components/panels/inspector/TaskDependencies.vue +1 -1
- package/app/components/panels/inspector/TaskEstimateBadge.vue +1 -1
- package/app/components/panels/inspector/TaskExecution.vue +9 -9
- package/app/components/panels/inspector/TaskRunSettings.vue +2 -2
- package/app/components/panels/inspector/TaskStructure.vue +1 -1
- package/app/components/pipeline/IterationCapPrompt.vue +1 -0
- package/app/components/pipeline/PipelineBuilder.vue +8 -8
- package/app/components/pipeline/PipelineProgress.vue +4 -4
- package/app/components/providers/ApiKeysSection.vue +2 -2
- package/app/components/providers/PersonalSubscriptionSection.vue +2 -2
- package/app/components/providers/VendorCredentialsModal.vue +2 -2
- package/app/components/provisioning/ProvisioningLogsDrawer.vue +1 -1
- package/app/components/requirements/RequirementsReviewWindow.vue +9 -8
- package/app/components/sandbox/SandboxPanel.vue +17 -17
- package/app/components/settings/LocalModelEndpointsPanel.vue +1 -1
- package/app/components/settings/ModelConfigurationPanel.vue +4 -3
- package/app/components/settings/OpenRouterCatalogPanel.vue +3 -3
- package/app/components/settings/ServiceFragmentDefaultsPanel.vue +1 -1
- package/app/components/spec/ServiceSpecWindow.vue +3 -3
- package/app/components/tasks/ContextIssuePicker.vue +5 -5
- package/app/components/tasks/TaskContextIssues.vue +1 -1
- package/app/components/tasks/TaskImportModal.vue +1 -1
- package/app/components/testing/TestReportWindow.vue +5 -5
- package/app/components/visualConfirm/VisualConfirmationWindow.vue +2 -2
- package/app/composables/usePipelineErrorToast.ts +37 -4
- package/app/pages/index.vue +1 -1
- package/app/stores/ui.ts +21 -0
- package/i18n/i18n.config.ts +9 -0
- package/i18n/locales/en.json +5 -0
- package/i18n/locales/es.json +5 -0
- package/i18n/locales/fr.json +5 -0
- package/i18n/locales/he.json +3390 -0
- package/i18n/locales/pl.json +5 -0
- package/i18n/locales/uk.json +5 -0
- package/nuxt.config.ts +1 -0
- package/package.json +2 -2
|
@@ -203,12 +203,12 @@ onMounted(() => {
|
|
|
203
203
|
v-for="row in importedRows"
|
|
204
204
|
:key="`imp:${row.externalId}`"
|
|
205
205
|
type="button"
|
|
206
|
-
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-
|
|
206
|
+
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-slate-300 hover:bg-slate-800/70"
|
|
207
207
|
@click="pickImported(row)"
|
|
208
208
|
>
|
|
209
209
|
<UIcon :name="icon" class="h-3.5 w-3.5 shrink-0 text-indigo-400" />
|
|
210
210
|
<span class="truncate">{{ row.externalId }} · {{ row.title }}</span>
|
|
211
|
-
<UBadge color="neutral" variant="soft" size="xs" class="
|
|
211
|
+
<UBadge color="neutral" variant="soft" size="xs" class="ms-auto shrink-0">{{
|
|
212
212
|
t('tasks.picker.imported')
|
|
213
213
|
}}</UBadge>
|
|
214
214
|
</button>
|
|
@@ -218,12 +218,12 @@ onMounted(() => {
|
|
|
218
218
|
v-for="r in searchRows"
|
|
219
219
|
:key="`hit:${r.externalId}`"
|
|
220
220
|
type="button"
|
|
221
|
-
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-
|
|
221
|
+
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-slate-300 hover:bg-slate-800/70"
|
|
222
222
|
@click="pickSearch(r)"
|
|
223
223
|
>
|
|
224
224
|
<UIcon :name="icon" class="h-3.5 w-3.5 shrink-0 text-slate-400" />
|
|
225
225
|
<span class="truncate">{{ r.externalId }} · {{ r.title }}</span>
|
|
226
|
-
<UBadge v-if="r.status" color="neutral" variant="soft" size="xs" class="
|
|
226
|
+
<UBadge v-if="r.status" color="neutral" variant="soft" size="xs" class="ms-auto shrink-0">
|
|
227
227
|
{{ r.status }}
|
|
228
228
|
</UBadge>
|
|
229
229
|
</button>
|
|
@@ -232,7 +232,7 @@ onMounted(() => {
|
|
|
232
232
|
<button
|
|
233
233
|
v-if="refRow"
|
|
234
234
|
type="button"
|
|
235
|
-
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-
|
|
235
|
+
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-slate-300 hover:bg-slate-800/70"
|
|
236
236
|
@click="pickRef(refRow)"
|
|
237
237
|
>
|
|
238
238
|
<UIcon name="i-lucide-link" class="h-3.5 w-3.5 shrink-0 text-slate-400" />
|
|
@@ -79,7 +79,7 @@ const attachMenu = computed<DropdownMenuItem[][]>(() => {
|
|
|
79
79
|
class="h-3.5 w-3.5 shrink-0 text-indigo-400"
|
|
80
80
|
/>
|
|
81
81
|
<span class="truncate">{{ task.externalId }} · {{ task.title }}</span>
|
|
82
|
-
<UBadge color="neutral" variant="soft" size="xs" class="
|
|
82
|
+
<UBadge color="neutral" variant="soft" size="xs" class="ms-auto shrink-0">
|
|
83
83
|
{{ task.status }}
|
|
84
84
|
</UBadge>
|
|
85
85
|
</a>
|
|
@@ -331,7 +331,7 @@ async function doSpawnEpic() {
|
|
|
331
331
|
>
|
|
332
332
|
<button
|
|
333
333
|
type="button"
|
|
334
|
-
class="min-w-0 flex-1 text-
|
|
334
|
+
class="min-w-0 flex-1 text-start disabled:cursor-not-allowed disabled:opacity-60"
|
|
335
335
|
:disabled="!containerId"
|
|
336
336
|
:title="
|
|
337
337
|
containerId
|
|
@@ -381,7 +381,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
381
381
|
</span>
|
|
382
382
|
<span
|
|
383
383
|
v-if="infraSetup.durationMs != null"
|
|
384
|
-
class="
|
|
384
|
+
class="ms-auto text-[11px] text-slate-500"
|
|
385
385
|
>
|
|
386
386
|
{{
|
|
387
387
|
t('testing.standup.took', {
|
|
@@ -484,7 +484,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
484
484
|
: t('testing.fixerTimeline.failed')
|
|
485
485
|
}}
|
|
486
486
|
</UBadge>
|
|
487
|
-
<span class="
|
|
487
|
+
<span class="ms-auto text-[11px] text-slate-500">{{
|
|
488
488
|
d(new Date(a.at), 'short')
|
|
489
489
|
}}</span>
|
|
490
490
|
</div>
|
|
@@ -541,7 +541,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
541
541
|
class="overflow-hidden rounded-lg border border-slate-800 bg-slate-900/60"
|
|
542
542
|
>
|
|
543
543
|
<button
|
|
544
|
-
class="flex w-full items-center gap-2 px-3 py-2 text-
|
|
544
|
+
class="flex w-full items-center gap-2 px-3 py-2 text-start hover:bg-slate-800/40"
|
|
545
545
|
@click="toggle(g.key)"
|
|
546
546
|
>
|
|
547
547
|
<UIcon
|
|
@@ -584,7 +584,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
584
584
|
</span>
|
|
585
585
|
</button>
|
|
586
586
|
|
|
587
|
-
<div v-if="!collapsed.has(g.key)" class="space-y-1 px-3 pb-3
|
|
587
|
+
<div v-if="!collapsed.has(g.key)" class="space-y-1 px-3 pb-3 ps-9">
|
|
588
588
|
<!-- Outcomes -->
|
|
589
589
|
<div
|
|
590
590
|
v-for="(o, oi) in g.outcomes"
|
|
@@ -710,7 +710,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
710
710
|
|
|
711
711
|
<!-- Sidebar: metadata -->
|
|
712
712
|
<aside
|
|
713
|
-
class="hidden w-60 shrink-0 flex-col gap-4 border-
|
|
713
|
+
class="hidden w-60 shrink-0 flex-col gap-4 border-s border-slate-800 bg-slate-900/50 px-4 py-4 lg:flex"
|
|
714
714
|
>
|
|
715
715
|
<div v-if="report">
|
|
716
716
|
<h4 class="mb-2 text-[11px] font-semibold uppercase tracking-wide text-slate-500">
|
|
@@ -315,7 +315,7 @@ const canApprove = computed(
|
|
|
315
315
|
type="file"
|
|
316
316
|
accept="image/png,image/jpeg"
|
|
317
317
|
:disabled="busy || !uploadView.trim()"
|
|
318
|
-
class="text-[12px] text-slate-300 file:
|
|
318
|
+
class="text-[12px] text-slate-300 file:me-2 file:rounded file:border-0 file:bg-slate-800 file:px-2 file:py-1 file:text-slate-200 disabled:opacity-40"
|
|
319
319
|
@change="onFilePicked"
|
|
320
320
|
/>
|
|
321
321
|
</div>
|
|
@@ -378,7 +378,7 @@ const canApprove = computed(
|
|
|
378
378
|
t('visualConfirm.history.fixRequested')
|
|
379
379
|
}}</span>
|
|
380
380
|
<span
|
|
381
|
-
class="
|
|
381
|
+
class="ms-1.5 rounded px-1 text-[10px] uppercase"
|
|
382
382
|
:class="
|
|
383
383
|
r.outcome === 'completed'
|
|
384
384
|
? 'bg-emerald-500/15 text-emerald-300'
|
|
@@ -28,10 +28,14 @@ interface ConflictDetails {
|
|
|
28
28
|
* fails THIS typecheck until it is mapped here. (The typed-message-keys feature can't see the
|
|
29
29
|
* `t()` lookup because the key is resolved at runtime via this map, not written as a literal —
|
|
30
30
|
* so the exhaustiveness of the map, not `t()`, is what makes a missing reason a build error.)
|
|
31
|
-
* `providers_unconfigured`
|
|
32
|
-
* key namespace, so
|
|
31
|
+
* `providers_unconfigured` and `binary_storage_unconfigured` are excluded: each has bespoke
|
|
32
|
+
* handling (a "configure X" action) + its own key namespace, so neither reaches the generic
|
|
33
|
+
* lookup below.
|
|
33
34
|
*/
|
|
34
|
-
const CONFLICT_TITLE_KEYS: Record<
|
|
35
|
+
const CONFLICT_TITLE_KEYS: Record<
|
|
36
|
+
Exclude<ConflictReason, 'providers_unconfigured' | 'binary_storage_unconfigured'>,
|
|
37
|
+
string
|
|
38
|
+
> = {
|
|
35
39
|
dependencies_unmet: 'errors.conflict.title.dependencies_unmet',
|
|
36
40
|
task_limit_reached: 'errors.conflict.title.task_limit_reached',
|
|
37
41
|
tester_infra_unsupported: 'errors.conflict.title.tester_infra_unsupported',
|
|
@@ -97,12 +101,41 @@ export function usePipelineErrorToast() {
|
|
|
97
101
|
return
|
|
98
102
|
}
|
|
99
103
|
|
|
104
|
+
// A pipeline step relies on binary-artifact storage (the UI Tester uploads screenshots)
|
|
105
|
+
// but the account has none configured. Explain it and offer the jump to the content-storage
|
|
106
|
+
// settings — the same shape as the providers-unconfigured case above. Prefer the localized
|
|
107
|
+
// body (it carries no runtime interpolation) so non-English users see translated copy; the
|
|
108
|
+
// raw backend prose is only the last-resort fallback when the locale lacks the key.
|
|
109
|
+
if (conflict?.reason === 'binary_storage_unconfigured') {
|
|
110
|
+
toast.add({
|
|
111
|
+
title: t('errors.conflict.binaryStorageUnconfigured.title'),
|
|
112
|
+
description: te('errors.conflict.binaryStorageUnconfigured.body')
|
|
113
|
+
? t('errors.conflict.binaryStorageUnconfigured.body')
|
|
114
|
+
: (conflict.message ?? t('errors.conflict.fallbackMessage')),
|
|
115
|
+
color: 'error',
|
|
116
|
+
icon: 'i-lucide-image',
|
|
117
|
+
actions: [
|
|
118
|
+
{
|
|
119
|
+
label: t('errors.conflict.binaryStorageUnconfigured.action'),
|
|
120
|
+
icon: 'i-lucide-settings',
|
|
121
|
+
onClick: () => ui.openContentStorageSettings(),
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
})
|
|
125
|
+
return
|
|
126
|
+
}
|
|
127
|
+
|
|
100
128
|
if (conflict) {
|
|
101
129
|
// Per-reason title key from the exhaustive map; fall back to the caller's title key when
|
|
102
130
|
// this reason has no mapped/translated copy (`te` = translation-exists, so a key missing
|
|
103
131
|
// in the active locale never leaks as raw text). An unknown reason isn't in the map.
|
|
104
132
|
const reasonKey =
|
|
105
|
-
CONFLICT_TITLE_KEYS[
|
|
133
|
+
CONFLICT_TITLE_KEYS[
|
|
134
|
+
conflict.reason as Exclude<
|
|
135
|
+
ConflictReason,
|
|
136
|
+
'providers_unconfigured' | 'binary_storage_unconfigured'
|
|
137
|
+
>
|
|
138
|
+
]
|
|
106
139
|
toast.add({
|
|
107
140
|
title: reasonKey && te(reasonKey) ? t(reasonKey) : t(fallbackTitleKey),
|
|
108
141
|
description: conflict.message ?? t('errors.conflict.fallbackMessage'),
|
package/app/pages/index.vue
CHANGED
|
@@ -243,7 +243,7 @@ watch(
|
|
|
243
243
|
<!-- z-30 keeps the trigger above the centered BoardToolbar (z-20), whose
|
|
244
244
|
max-width can otherwise reach this corner on the narrowest viewports. -->
|
|
245
245
|
<UButton
|
|
246
|
-
class="absolute
|
|
246
|
+
class="absolute start-3 top-3 z-30 lg:hidden"
|
|
247
247
|
icon="i-lucide-menu"
|
|
248
248
|
color="neutral"
|
|
249
249
|
variant="soft"
|
package/app/stores/ui.ts
CHANGED
|
@@ -121,6 +121,11 @@ export const useUiStore = defineStore('ui', () => {
|
|
|
121
121
|
// straight to a tab.
|
|
122
122
|
const accountSettingsOpen = ref(false)
|
|
123
123
|
const accountSettingsTab = ref('team')
|
|
124
|
+
// A one-shot deep-link anchor: when a surface opens account settings AND wants to land on a
|
|
125
|
+
// specific section within the (long) tab body, it sets this to that section's id. The owning
|
|
126
|
+
// panel scrolls the matching element into view once, then calls `clearAccountSettingsScrollTarget`
|
|
127
|
+
// so a later plain open doesn't re-scroll. Null when no section was requested.
|
|
128
|
+
const accountSettingsScrollTarget = ref<string | null>(null)
|
|
124
129
|
// Observability integration: the post-release-health connection panel (Datadog
|
|
125
130
|
// today, pluggable). NB: distinct from `observabilityInstanceId` below, which is the
|
|
126
131
|
// LLM per-call observability panel.
|
|
@@ -464,8 +469,21 @@ export const useUiStore = defineStore('ui', () => {
|
|
|
464
469
|
accountSettingsTab.value = tab
|
|
465
470
|
accountSettingsOpen.value = true
|
|
466
471
|
}
|
|
472
|
+
// Deep-link to the content (binary-artifact) storage configuration, which lives near the
|
|
473
|
+
// bottom of the account settings' team tab (`AccountDeploymentSettings`). Used by the
|
|
474
|
+
// pipeline-start error prompt when a storage-reliant agent (the UI Tester) has no storage
|
|
475
|
+
// configured. Sets a scroll anchor so the panel brings the storage section into view rather
|
|
476
|
+
// than dropping the user at the top of the long team tab to hunt for it.
|
|
477
|
+
function openContentStorageSettings() {
|
|
478
|
+
accountSettingsScrollTarget.value = 'content-storage'
|
|
479
|
+
openAccountSettings('team')
|
|
480
|
+
}
|
|
481
|
+
function clearAccountSettingsScrollTarget() {
|
|
482
|
+
accountSettingsScrollTarget.value = null
|
|
483
|
+
}
|
|
467
484
|
function closeAccountSettings() {
|
|
468
485
|
accountSettingsOpen.value = false
|
|
486
|
+
accountSettingsScrollTarget.value = null
|
|
469
487
|
}
|
|
470
488
|
function setAccountSettingsTab(tab: string) {
|
|
471
489
|
accountSettingsTab.value = tab
|
|
@@ -664,6 +682,7 @@ export const useUiStore = defineStore('ui', () => {
|
|
|
664
682
|
workspaceSettingsTab,
|
|
665
683
|
accountSettingsOpen,
|
|
666
684
|
accountSettingsTab,
|
|
685
|
+
accountSettingsScrollTarget,
|
|
667
686
|
observabilityConnectionOpen,
|
|
668
687
|
infrastructureOpen,
|
|
669
688
|
infrastructureTab,
|
|
@@ -739,6 +758,8 @@ export const useUiStore = defineStore('ui', () => {
|
|
|
739
758
|
closeWorkspaceSettings,
|
|
740
759
|
setWorkspaceSettingsTab,
|
|
741
760
|
openAccountSettings,
|
|
761
|
+
openContentStorageSettings,
|
|
762
|
+
clearAccountSettingsScrollTarget,
|
|
742
763
|
closeAccountSettings,
|
|
743
764
|
setAccountSettingsTab,
|
|
744
765
|
openObservabilityConnection,
|
package/i18n/i18n.config.ts
CHANGED
|
@@ -61,6 +61,11 @@ export default defineI18nConfig(() => ({
|
|
|
61
61
|
currency: { style: 'currency', currency: 'USD', currencyDisplay: 'narrowSymbol' },
|
|
62
62
|
percent: { style: 'percent', maximumFractionDigits: 1 },
|
|
63
63
|
},
|
|
64
|
+
he: {
|
|
65
|
+
decimal: { style: 'decimal' },
|
|
66
|
+
currency: { style: 'currency', currency: 'USD', currencyDisplay: 'narrowSymbol' },
|
|
67
|
+
percent: { style: 'percent', maximumFractionDigits: 1 },
|
|
68
|
+
},
|
|
64
69
|
},
|
|
65
70
|
datetimeFormats: {
|
|
66
71
|
en: {
|
|
@@ -83,5 +88,9 @@ export default defineI18nConfig(() => ({
|
|
|
83
88
|
short: { dateStyle: 'medium' },
|
|
84
89
|
long: { dateStyle: 'long', timeStyle: 'short' },
|
|
85
90
|
},
|
|
91
|
+
he: {
|
|
92
|
+
short: { dateStyle: 'medium' },
|
|
93
|
+
long: { dateStyle: 'long', timeStyle: 'short' },
|
|
94
|
+
},
|
|
86
95
|
},
|
|
87
96
|
}))
|
package/i18n/locales/en.json
CHANGED
|
@@ -292,6 +292,11 @@
|
|
|
292
292
|
"description": "Keep the named placeholder for the model list intact (a comma-separated list of model ids is injected at runtime)."
|
|
293
293
|
},
|
|
294
294
|
"action": "Configure AI"
|
|
295
|
+
},
|
|
296
|
+
"binaryStorageUnconfigured": {
|
|
297
|
+
"title": "No storage for this pipeline",
|
|
298
|
+
"body": "This pipeline includes an agent that needs binary storage (the UI Tester uploads its screenshots), but this account has no content storage configured. Configure content storage to run it.",
|
|
299
|
+
"action": "Configure storage"
|
|
295
300
|
}
|
|
296
301
|
}
|
|
297
302
|
},
|
package/i18n/locales/es.json
CHANGED
|
@@ -259,6 +259,11 @@
|
|
|
259
259
|
"title": "No hay proveedor de IA para este modelo",
|
|
260
260
|
"body": "No hay ningún proveedor configurado para {models}. Añade una clave de proveedor, conecta una suscripción o activa Cloudflare AI para ejecutarlo.",
|
|
261
261
|
"action": "Configurar IA"
|
|
262
|
+
},
|
|
263
|
+
"binaryStorageUnconfigured": {
|
|
264
|
+
"title": "No hay almacenamiento para esta canalización",
|
|
265
|
+
"body": "Esta canalización incluye un agente que necesita almacenamiento binario (el probador de UI sube sus capturas de pantalla), pero esta cuenta no tiene almacenamiento de contenido configurado. Configura el almacenamiento de contenido para ejecutarla.",
|
|
266
|
+
"action": "Configurar almacenamiento"
|
|
262
267
|
}
|
|
263
268
|
}
|
|
264
269
|
},
|
package/i18n/locales/fr.json
CHANGED
|
@@ -259,6 +259,11 @@
|
|
|
259
259
|
"title": "Aucun fournisseur d’IA pour ce modèle",
|
|
260
260
|
"body": "Aucun fournisseur n’est configuré pour {models}. Ajoutez une clé de fournisseur, connectez un abonnement ou activez Cloudflare AI pour l’exécuter.",
|
|
261
261
|
"action": "Configurer l’IA"
|
|
262
|
+
},
|
|
263
|
+
"binaryStorageUnconfigured": {
|
|
264
|
+
"title": "Aucun stockage pour ce pipeline",
|
|
265
|
+
"body": "Ce pipeline inclut un agent qui a besoin d’un stockage binaire (le testeur d’UI téléverse ses captures d’écran), mais aucun stockage de contenu n’est configuré pour ce compte. Configurez le stockage de contenu pour l’exécuter.",
|
|
266
|
+
"action": "Configurer le stockage"
|
|
262
267
|
}
|
|
263
268
|
}
|
|
264
269
|
},
|