@cat-factory/app 0.46.10 → 0.46.11
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/components/observability/StepMetricsBar.vue +31 -11
- package/app/components/observability/StepModelActivity.vue +3 -2
- package/app/components/panels/AgentStepDetail.vue +52 -39
- package/app/components/panels/DecisionModal.vue +12 -5
- package/app/components/panels/GenericStructuredResultView.vue +16 -6
- package/app/components/panels/InspectorPanel.vue +35 -28
- package/app/components/panels/ObservabilityPanel.vue +92 -49
- package/app/components/panels/StepMetadataCard.vue +87 -30
- package/app/components/panels/StepRestartControl.vue +4 -3
- package/app/components/panels/StepRunMeta.vue +23 -10
- package/app/components/panels/StepTestReport.vue +14 -11
- package/app/components/panels/inspector/ContainerSummary.vue +25 -14
- package/app/components/panels/inspector/EpicChildren.vue +7 -4
- package/app/components/panels/inspector/RecurringScheduleSettings.vue +60 -19
- package/app/components/panels/inspector/ServiceFragments.vue +3 -2
- package/app/components/panels/inspector/ServiceReleaseHealthConfig.vue +18 -13
- package/app/components/panels/inspector/ServiceTestConfig.vue +50 -39
- package/app/components/panels/inspector/TaskAgentConfig.vue +6 -5
- package/app/components/panels/inspector/TaskDependencies.vue +9 -4
- package/app/components/panels/inspector/TaskEstimateBadge.vue +14 -13
- package/app/components/panels/inspector/TaskExecution.vue +65 -31
- package/app/components/panels/inspector/TaskRunSettings.vue +93 -56
- package/app/components/panels/inspector/TaskStructure.vue +5 -4
- package/i18n/locales/en.json +402 -0
- package/i18n/locales/es.json +402 -0
- package/i18n/locales/fr.json +402 -0
- package/i18n/locales/pl.json +402 -0
- package/i18n/locales/uk.json +402 -0
- package/package.json +1 -1
|
@@ -19,6 +19,8 @@ import {
|
|
|
19
19
|
const props = defineProps<{ metrics: StepMetrics; clickable?: boolean }>()
|
|
20
20
|
defineEmits<{ inspect: [] }>()
|
|
21
21
|
|
|
22
|
+
const { t } = useI18n()
|
|
23
|
+
|
|
22
24
|
const m = computed(() => props.metrics)
|
|
23
25
|
const headroom = computed(() => headroomRatio(m.value))
|
|
24
26
|
const transport = computed(() => transportRatio(m.value))
|
|
@@ -38,24 +40,33 @@ const headroomTone = computed(() => headroomColor(headroom.value, m.value.trunca
|
|
|
38
40
|
<!-- header line: call count + tokens + warning/error badges -->
|
|
39
41
|
<div class="flex items-center gap-2">
|
|
40
42
|
<UIcon name="i-lucide-activity" class="h-3.5 w-3.5 shrink-0 text-slate-500" />
|
|
41
|
-
<span class="text-slate-300">
|
|
43
|
+
<span class="text-slate-300">
|
|
44
|
+
{{ t('observability.metricsBar.calls', { count: m.calls }, m.calls) }}
|
|
45
|
+
</span>
|
|
42
46
|
<span class="text-slate-500">·</span>
|
|
43
|
-
<span
|
|
47
|
+
<span
|
|
48
|
+
class="tabular-nums text-slate-400"
|
|
49
|
+
:title="t('observability.metricsBar.promptCompletionTokens')"
|
|
50
|
+
>
|
|
44
51
|
{{ formatTokens(m.promptTokens) }}↑ {{ formatTokens(m.completionTokens) }}↓
|
|
45
52
|
</span>
|
|
46
53
|
<span
|
|
47
54
|
v-if="(m.cachedPromptTokens ?? 0) > 0"
|
|
48
55
|
class="tabular-nums text-emerald-400/80"
|
|
49
|
-
title="
|
|
56
|
+
:title="t('observability.metricsBar.cachedTokensHint')"
|
|
50
57
|
>
|
|
51
|
-
|
|
58
|
+
{{
|
|
59
|
+
t('observability.metricsBar.cachedTokens', {
|
|
60
|
+
tokens: formatTokens(m.cachedPromptTokens ?? 0),
|
|
61
|
+
})
|
|
62
|
+
}}
|
|
52
63
|
</span>
|
|
53
64
|
<div class="ml-auto flex items-center gap-1">
|
|
54
65
|
<UBadge v-if="m.errors > 0" color="error" variant="subtle" size="sm">
|
|
55
|
-
{{
|
|
66
|
+
{{ t('observability.metricsBar.errors', { count: m.errors }, m.errors) }}
|
|
56
67
|
</UBadge>
|
|
57
68
|
<UBadge v-if="m.warnings > 0" color="warning" variant="subtle" size="sm">
|
|
58
|
-
{{
|
|
69
|
+
{{ t('observability.metricsBar.warnings', { count: m.warnings }, m.warnings) }}
|
|
59
70
|
</UBadge>
|
|
60
71
|
<UIcon v-if="clickable" name="i-lucide-chevron-right" class="h-3.5 w-3.5 text-slate-600" />
|
|
61
72
|
</div>
|
|
@@ -64,7 +75,7 @@ const headroomTone = computed(() => headroomColor(headroom.value, m.value.trunca
|
|
|
64
75
|
<!-- output-limit headroom -->
|
|
65
76
|
<div v-if="headroom !== null" class="mt-2">
|
|
66
77
|
<div class="flex items-center justify-between text-[11px]">
|
|
67
|
-
<span class="text-slate-500">
|
|
78
|
+
<span class="text-slate-500">{{ t('observability.metricsBar.outputLimit') }}</span>
|
|
68
79
|
<span class="tabular-nums" :class="headroomTone">
|
|
69
80
|
{{ formatTokens(m.peakCompletionTokens) }} /
|
|
70
81
|
{{ formatTokens(m.maxOutputTokens ?? 0) }} ({{ pct(headroom) }}%)
|
|
@@ -84,14 +95,20 @@ const headroomTone = computed(() => headroomColor(headroom.value, m.value.trunca
|
|
|
84
95
|
/>
|
|
85
96
|
</div>
|
|
86
97
|
<p v-if="m.truncatedCalls > 0" class="mt-1 text-[11px] text-rose-400">
|
|
87
|
-
{{
|
|
98
|
+
{{
|
|
99
|
+
t(
|
|
100
|
+
'observability.metricsBar.truncatedCalls',
|
|
101
|
+
{ count: m.truncatedCalls },
|
|
102
|
+
m.truncatedCalls,
|
|
103
|
+
)
|
|
104
|
+
}}
|
|
88
105
|
</p>
|
|
89
106
|
</div>
|
|
90
107
|
|
|
91
108
|
<!-- transport overhead vs model execution -->
|
|
92
109
|
<div v-if="transport !== null" class="mt-2">
|
|
93
110
|
<div class="flex items-center justify-between text-[11px]">
|
|
94
|
-
<span class="text-slate-500">
|
|
111
|
+
<span class="text-slate-500">{{ t('observability.metricsBar.transportVsExecution') }}</span>
|
|
95
112
|
<span class="tabular-nums text-slate-400">
|
|
96
113
|
{{ formatMs(m.overheadMs) }} / {{ formatMs(m.upstreamMs) }}
|
|
97
114
|
</span>
|
|
@@ -100,9 +117,12 @@ const headroomTone = computed(() => headroomColor(headroom.value, m.value.trunca
|
|
|
100
117
|
<div
|
|
101
118
|
class="h-full bg-sky-400/80"
|
|
102
119
|
:style="{ width: `${pct(transport)}%` }"
|
|
103
|
-
title="
|
|
120
|
+
:title="t('observability.metricsBar.transportOverhead')"
|
|
121
|
+
/>
|
|
122
|
+
<div
|
|
123
|
+
class="h-full bg-indigo-400/80 flex-1"
|
|
124
|
+
:title="t('observability.metricsBar.modelExecution')"
|
|
104
125
|
/>
|
|
105
|
-
<div class="h-full bg-indigo-400/80 flex-1" title="Model execution" />
|
|
106
126
|
</div>
|
|
107
127
|
</div>
|
|
108
128
|
</div>
|
|
@@ -18,6 +18,7 @@ const props = defineProps<{
|
|
|
18
18
|
}>()
|
|
19
19
|
|
|
20
20
|
const ui = useUiStore()
|
|
21
|
+
const { t } = useI18n()
|
|
21
22
|
const hasCalls = computed(() => !!props.metrics && props.metrics.calls > 0)
|
|
22
23
|
|
|
23
24
|
function openObservability() {
|
|
@@ -29,14 +30,14 @@ function openObservability() {
|
|
|
29
30
|
<div v-if="instanceId || hasCalls">
|
|
30
31
|
<div class="mb-1 flex items-center justify-between">
|
|
31
32
|
<span class="text-[11px] font-semibold uppercase tracking-wide text-slate-500">
|
|
32
|
-
|
|
33
|
+
{{ t('observability.modelActivity') }}
|
|
33
34
|
</span>
|
|
34
35
|
<button
|
|
35
36
|
v-if="instanceId"
|
|
36
37
|
class="text-[11px] text-sky-400 hover:text-sky-300"
|
|
37
38
|
@click="openObservability"
|
|
38
39
|
>
|
|
39
|
-
|
|
40
|
+
{{ t('observability.viewAllCalls') }}
|
|
40
41
|
</button>
|
|
41
42
|
</div>
|
|
42
43
|
<StepMetricsBar
|
|
@@ -27,6 +27,7 @@ const execution = useExecutionStore()
|
|
|
27
27
|
const board = useBoardStore()
|
|
28
28
|
const models = useModelsStore()
|
|
29
29
|
const workspace = useWorkspaceStore()
|
|
30
|
+
const { t } = useI18n()
|
|
30
31
|
|
|
31
32
|
onMounted(() => models.ensureLoaded(workspace.workspaceId ?? undefined))
|
|
32
33
|
|
|
@@ -187,7 +188,7 @@ async function copyOutput() {
|
|
|
187
188
|
>
|
|
188
189
|
<div class="border-b border-slate-800 px-4 py-3">
|
|
189
190
|
<div class="text-[11px] font-semibold uppercase tracking-wide text-slate-500">
|
|
190
|
-
|
|
191
|
+
{{ t('panels.stepDetail.contents') }}
|
|
191
192
|
</div>
|
|
192
193
|
</div>
|
|
193
194
|
<nav class="flex-1 space-y-0.5 overflow-auto px-2 py-3">
|
|
@@ -200,7 +201,7 @@ async function copyOutput() {
|
|
|
200
201
|
"
|
|
201
202
|
@click="goTo('step-details')"
|
|
202
203
|
>
|
|
203
|
-
|
|
204
|
+
{{ t('panels.stepDetail.details') }}
|
|
204
205
|
</button>
|
|
205
206
|
<button
|
|
206
207
|
v-for="s in tocSections"
|
|
@@ -242,7 +243,7 @@ async function copyOutput() {
|
|
|
242
243
|
class="mr-1"
|
|
243
244
|
>
|
|
244
245
|
<UIcon name="i-lucide-shield-check" class="mr-1 h-3 w-3" />
|
|
245
|
-
|
|
246
|
+
{{ t('panels.stepDetail.approvalRequired') }}
|
|
246
247
|
</UBadge>
|
|
247
248
|
<UBadge
|
|
248
249
|
v-else-if="companionExceeded"
|
|
@@ -252,7 +253,7 @@ async function copyOutput() {
|
|
|
252
253
|
class="mr-1"
|
|
253
254
|
>
|
|
254
255
|
<UIcon name="i-lucide-alert-triangle" class="mr-1 h-3 w-3" />
|
|
255
|
-
|
|
256
|
+
{{ t('panels.stepDetail.decisionRequired') }}
|
|
256
257
|
</UBadge>
|
|
257
258
|
<UButton
|
|
258
259
|
v-if="outline.sections.length"
|
|
@@ -260,7 +261,11 @@ async function copyOutput() {
|
|
|
260
261
|
color="neutral"
|
|
261
262
|
variant="ghost"
|
|
262
263
|
size="sm"
|
|
263
|
-
:title="
|
|
264
|
+
:title="
|
|
265
|
+
allCollapsed
|
|
266
|
+
? t('panels.stepDetail.expandAll')
|
|
267
|
+
: t('panels.stepDetail.collapseAll')
|
|
268
|
+
"
|
|
264
269
|
@click="setAll(!allCollapsed)"
|
|
265
270
|
/>
|
|
266
271
|
<UButton
|
|
@@ -269,7 +274,7 @@ async function copyOutput() {
|
|
|
269
274
|
color="neutral"
|
|
270
275
|
variant="ghost"
|
|
271
276
|
size="sm"
|
|
272
|
-
title="
|
|
277
|
+
:title="t('panels.stepDetail.copyRawOutput')"
|
|
273
278
|
@click="copyOutput"
|
|
274
279
|
/>
|
|
275
280
|
<!-- Restart the pipeline from this step (shared two-click confirm; resetting
|
|
@@ -286,7 +291,7 @@ async function copyOutput() {
|
|
|
286
291
|
color="neutral"
|
|
287
292
|
variant="ghost"
|
|
288
293
|
size="sm"
|
|
289
|
-
title="
|
|
294
|
+
:title="t('panels.stepDetail.closeEsc')"
|
|
290
295
|
@click="close"
|
|
291
296
|
/>
|
|
292
297
|
</div>
|
|
@@ -323,8 +328,14 @@ async function copyOutput() {
|
|
|
323
328
|
(one more round / proceed with the current output / stop & reset) -->
|
|
324
329
|
<IterationCapPrompt
|
|
325
330
|
v-if="companionExceeded"
|
|
326
|
-
:heading="
|
|
327
|
-
|
|
331
|
+
:heading="
|
|
332
|
+
t('panels.stepDetail.companionCapHeading', {
|
|
333
|
+
agent: agent.label,
|
|
334
|
+
attempts: step.companion?.maxAttempts,
|
|
335
|
+
threshold: pctOf(latestVerdict?.threshold ?? 0),
|
|
336
|
+
})
|
|
337
|
+
"
|
|
338
|
+
:detail="t('panels.stepDetail.companionCapDetail')"
|
|
328
339
|
:loading="resolvingCap"
|
|
329
340
|
@resolve="resolveCompanionCap"
|
|
330
341
|
/>
|
|
@@ -344,7 +355,9 @@ async function copyOutput() {
|
|
|
344
355
|
@click="showProvisioning = !showProvisioning"
|
|
345
356
|
>
|
|
346
357
|
{{
|
|
347
|
-
showProvisioning
|
|
358
|
+
showProvisioning
|
|
359
|
+
? t('panels.stepDetail.hideInfraAttempts')
|
|
360
|
+
: t('panels.stepDetail.infraAttempts')
|
|
348
361
|
}}
|
|
349
362
|
</UButton>
|
|
350
363
|
<ProvisioningLogsDrawer
|
|
@@ -363,7 +376,9 @@ async function copyOutput() {
|
|
|
363
376
|
<section v-if="editing" class="scroll-mt-4">
|
|
364
377
|
<div class="mb-2 flex items-center gap-1.5 text-[11px] text-amber-400">
|
|
365
378
|
<UIcon name="i-lucide-pencil" class="h-3.5 w-3.5" />
|
|
366
|
-
<span class="font-semibold uppercase tracking-wide">
|
|
379
|
+
<span class="font-semibold uppercase tracking-wide">{{
|
|
380
|
+
t('panels.stepDetail.editingConclusions')
|
|
381
|
+
}}</span>
|
|
367
382
|
</div>
|
|
368
383
|
<UTextarea
|
|
369
384
|
v-model="draftProposal"
|
|
@@ -372,7 +387,7 @@ async function copyOutput() {
|
|
|
372
387
|
size="sm"
|
|
373
388
|
class="w-full"
|
|
374
389
|
:ui="{ base: 'font-mono text-[12px] leading-relaxed' }"
|
|
375
|
-
placeholder="
|
|
390
|
+
:placeholder="t('panels.stepDetail.editConclusionsPlaceholder')"
|
|
376
391
|
/>
|
|
377
392
|
</section>
|
|
378
393
|
|
|
@@ -419,7 +434,7 @@ async function copyOutput() {
|
|
|
419
434
|
v-else
|
|
420
435
|
class="rounded-lg border border-dashed border-slate-800 py-6 text-center text-sm text-slate-500"
|
|
421
436
|
>
|
|
422
|
-
|
|
437
|
+
{{ t('panels.stepDetail.noProseOutput') }}
|
|
423
438
|
</p>
|
|
424
439
|
</div>
|
|
425
440
|
</div>
|
|
@@ -434,14 +449,14 @@ async function copyOutput() {
|
|
|
434
449
|
>
|
|
435
450
|
<div class="border-b border-slate-800 px-4 py-3">
|
|
436
451
|
<div class="text-[11px] font-semibold uppercase tracking-wide text-amber-400">
|
|
437
|
-
{{ editing ? 'Approve with corrections' : 'Review & approve' }}
|
|
438
|
-
</div>
|
|
439
|
-
<p class="mt-1 text-[12px] text-slate-400">
|
|
440
452
|
{{
|
|
441
453
|
editing
|
|
442
|
-
? '
|
|
443
|
-
: '
|
|
454
|
+
? t('panels.stepDetail.approveWithCorrections')
|
|
455
|
+
: t('panels.stepDetail.reviewAndApprove')
|
|
444
456
|
}}
|
|
457
|
+
</div>
|
|
458
|
+
<p class="mt-1 text-[12px] text-slate-400">
|
|
459
|
+
{{ editing ? t('panels.stepDetail.editHint') : t('panels.stepDetail.reviewHint') }}
|
|
445
460
|
</p>
|
|
446
461
|
</div>
|
|
447
462
|
|
|
@@ -450,8 +465,7 @@ async function copyOutput() {
|
|
|
450
465
|
v-if="editing"
|
|
451
466
|
class="rounded-lg border border-amber-500/30 bg-amber-500/5 p-3 text-[12px] leading-relaxed text-amber-200/90"
|
|
452
467
|
>
|
|
453
|
-
|
|
454
|
-
comments — approve to save them, or cancel to return to review.
|
|
468
|
+
{{ t('panels.stepDetail.editingNotice') }}
|
|
455
469
|
</p>
|
|
456
470
|
<template v-else>
|
|
457
471
|
<!-- composer for the block the human just clicked -->
|
|
@@ -460,7 +474,7 @@ async function copyOutput() {
|
|
|
460
474
|
class="rounded-lg border border-indigo-500/40 bg-indigo-500/5 p-3"
|
|
461
475
|
>
|
|
462
476
|
<div class="mb-1 text-[10px] uppercase tracking-wide text-indigo-300">
|
|
463
|
-
|
|
477
|
+
{{ t('panels.stepDetail.commentingOn') }}
|
|
464
478
|
</div>
|
|
465
479
|
<pre
|
|
466
480
|
class="mb-2 max-h-24 overflow-auto whitespace-pre-wrap rounded bg-slate-950/60 p-2 text-[11px] text-slate-300"
|
|
@@ -472,11 +486,11 @@ async function copyOutput() {
|
|
|
472
486
|
autoresize
|
|
473
487
|
size="sm"
|
|
474
488
|
class="w-full"
|
|
475
|
-
placeholder="
|
|
489
|
+
:placeholder="t('panels.stepDetail.commentPlaceholder')"
|
|
476
490
|
/>
|
|
477
491
|
<div class="mt-2 flex justify-end gap-2">
|
|
478
492
|
<UButton color="neutral" variant="ghost" size="xs" @click="cancelDraft">
|
|
479
|
-
|
|
493
|
+
{{ t('common.cancel') }}
|
|
480
494
|
</UButton>
|
|
481
495
|
<UButton
|
|
482
496
|
color="primary"
|
|
@@ -484,7 +498,7 @@ async function copyOutput() {
|
|
|
484
498
|
:disabled="!draftBody.trim()"
|
|
485
499
|
@click="addDraftComment"
|
|
486
500
|
>
|
|
487
|
-
|
|
501
|
+
{{ t('panels.stepDetail.addComment') }}
|
|
488
502
|
</UButton>
|
|
489
503
|
</div>
|
|
490
504
|
</div>
|
|
@@ -497,11 +511,11 @@ async function copyOutput() {
|
|
|
497
511
|
>
|
|
498
512
|
<div class="mb-1 flex items-start justify-between gap-2">
|
|
499
513
|
<div class="text-[10px] uppercase tracking-wide text-slate-500">
|
|
500
|
-
|
|
514
|
+
{{ t('panels.stepDetail.commentN', { number: idx + 1 }) }}
|
|
501
515
|
</div>
|
|
502
516
|
<button
|
|
503
517
|
class="text-slate-500 transition hover:text-rose-400"
|
|
504
|
-
title="
|
|
518
|
+
:title="t('panels.stepDetail.removeComment')"
|
|
505
519
|
@click="removeComment(idx)"
|
|
506
520
|
>
|
|
507
521
|
<UIcon name="i-lucide-x" class="h-3.5 w-3.5" />
|
|
@@ -518,7 +532,7 @@ async function copyOutput() {
|
|
|
518
532
|
<label
|
|
519
533
|
class="mb-1 block text-[11px] font-semibold uppercase tracking-wide text-slate-400"
|
|
520
534
|
>
|
|
521
|
-
|
|
535
|
+
{{ t('panels.stepDetail.overallFeedback') }}
|
|
522
536
|
</label>
|
|
523
537
|
<UTextarea
|
|
524
538
|
v-model="feedback"
|
|
@@ -526,7 +540,7 @@ async function copyOutput() {
|
|
|
526
540
|
autoresize
|
|
527
541
|
size="sm"
|
|
528
542
|
class="w-full"
|
|
529
|
-
placeholder="
|
|
543
|
+
:placeholder="t('panels.stepDetail.overallFeedbackPlaceholder')"
|
|
530
544
|
/>
|
|
531
545
|
</div>
|
|
532
546
|
</template>
|
|
@@ -542,7 +556,7 @@ async function copyOutput() {
|
|
|
542
556
|
:loading="submitting"
|
|
543
557
|
@click="approveWithEdits"
|
|
544
558
|
>
|
|
545
|
-
|
|
559
|
+
{{ t('panels.stepDetail.approveWithEdits') }}
|
|
546
560
|
</UButton>
|
|
547
561
|
<UButton
|
|
548
562
|
color="neutral"
|
|
@@ -552,7 +566,7 @@ async function copyOutput() {
|
|
|
552
566
|
:disabled="submitting"
|
|
553
567
|
@click="cancelEditing"
|
|
554
568
|
>
|
|
555
|
-
|
|
569
|
+
{{ t('panels.stepDetail.cancelEdits') }}
|
|
556
570
|
</UButton>
|
|
557
571
|
</div>
|
|
558
572
|
|
|
@@ -567,7 +581,7 @@ async function copyOutput() {
|
|
|
567
581
|
:loading="submitting"
|
|
568
582
|
@click="approve"
|
|
569
583
|
>
|
|
570
|
-
|
|
584
|
+
{{ t('panels.stepDetail.approveAndProceed') }}
|
|
571
585
|
</UButton>
|
|
572
586
|
<UButton
|
|
573
587
|
color="primary"
|
|
@@ -578,7 +592,7 @@ async function copyOutput() {
|
|
|
578
592
|
:disabled="rejectArmed || submitting"
|
|
579
593
|
@click="startEditing"
|
|
580
594
|
>
|
|
581
|
-
|
|
595
|
+
{{ t('panels.stepDetail.approveWithCorrections') }}
|
|
582
596
|
</UButton>
|
|
583
597
|
|
|
584
598
|
<!-- destructive: a two-step inline confirm instead of a native dialog -->
|
|
@@ -587,7 +601,7 @@ async function copyOutput() {
|
|
|
587
601
|
class="rounded-lg border border-rose-500/40 bg-rose-500/5 p-2.5"
|
|
588
602
|
>
|
|
589
603
|
<p class="mb-2 text-[11px] text-rose-200">
|
|
590
|
-
|
|
604
|
+
{{ t('panels.stepDetail.rejectConfirmPrompt') }}
|
|
591
605
|
</p>
|
|
592
606
|
<div class="flex gap-2">
|
|
593
607
|
<UButton
|
|
@@ -598,7 +612,7 @@ async function copyOutput() {
|
|
|
598
612
|
:disabled="submitting"
|
|
599
613
|
@click="disarmReject"
|
|
600
614
|
>
|
|
601
|
-
|
|
615
|
+
{{ t('common.cancel') }}
|
|
602
616
|
</UButton>
|
|
603
617
|
<UButton
|
|
604
618
|
color="error"
|
|
@@ -608,7 +622,7 @@ async function copyOutput() {
|
|
|
608
622
|
:loading="submitting"
|
|
609
623
|
@click="reject"
|
|
610
624
|
>
|
|
611
|
-
|
|
625
|
+
{{ t('panels.stepDetail.confirmReject') }}
|
|
612
626
|
</UButton>
|
|
613
627
|
</div>
|
|
614
628
|
</div>
|
|
@@ -623,7 +637,7 @@ async function copyOutput() {
|
|
|
623
637
|
:loading="submitting"
|
|
624
638
|
@click="requestChanges"
|
|
625
639
|
>
|
|
626
|
-
|
|
640
|
+
{{ t('panels.stepDetail.requestChanges') }}
|
|
627
641
|
</UButton>
|
|
628
642
|
<UButton
|
|
629
643
|
color="error"
|
|
@@ -634,12 +648,11 @@ async function copyOutput() {
|
|
|
634
648
|
:disabled="submitting"
|
|
635
649
|
@click="armReject"
|
|
636
650
|
>
|
|
637
|
-
|
|
651
|
+
{{ t('panels.stepDetail.reject') }}
|
|
638
652
|
</UButton>
|
|
639
653
|
</div>
|
|
640
654
|
<p class="text-[10px] text-slate-500">
|
|
641
|
-
|
|
642
|
-
run entirely.
|
|
655
|
+
{{ t('panels.stepDetail.requestChangesHint') }}
|
|
643
656
|
</p>
|
|
644
657
|
</div>
|
|
645
658
|
</aside>
|
|
@@ -4,6 +4,7 @@ import { agentKindMeta } from '~/utils/catalog'
|
|
|
4
4
|
const execution = useExecutionStore()
|
|
5
5
|
const board = useBoardStore()
|
|
6
6
|
const ui = useUiStore()
|
|
7
|
+
const { t } = useI18n()
|
|
7
8
|
|
|
8
9
|
const ctx = computed(() => ui.decisionContext)
|
|
9
10
|
|
|
@@ -30,7 +31,7 @@ function choose(option: string) {
|
|
|
30
31
|
</script>
|
|
31
32
|
|
|
32
33
|
<template>
|
|
33
|
-
<UModal v-model:open="open" title="
|
|
34
|
+
<UModal v-model:open="open" :title="t('panels.decision.title')">
|
|
34
35
|
<template #body>
|
|
35
36
|
<div v-if="decision && agent" class="space-y-4" data-testid="decision-modal">
|
|
36
37
|
<div class="flex items-center gap-2 text-sm text-slate-400">
|
|
@@ -41,9 +42,15 @@ function choose(option: string) {
|
|
|
41
42
|
<UIcon :name="agent.icon" class="h-4 w-4" :style="{ color: agent.color }" />
|
|
42
43
|
</div>
|
|
43
44
|
<div>
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
<i18n-t v-if="block" keypath="panels.decision.agentOnBlock" tag="span" scope="global">
|
|
46
|
+
<template #agent>
|
|
47
|
+
<span class="font-medium text-slate-200">{{ agent.label }}</span>
|
|
48
|
+
</template>
|
|
49
|
+
<template #block>
|
|
50
|
+
<span class="font-medium text-slate-200">{{ block.title }}</span>
|
|
51
|
+
</template>
|
|
52
|
+
</i18n-t>
|
|
53
|
+
<span v-else class="font-medium text-slate-200">{{ agent.label }}</span>
|
|
47
54
|
</div>
|
|
48
55
|
</div>
|
|
49
56
|
|
|
@@ -64,7 +71,7 @@ function choose(option: string) {
|
|
|
64
71
|
</UButton>
|
|
65
72
|
</div>
|
|
66
73
|
<p class="text-[11px] text-slate-500">
|
|
67
|
-
|
|
74
|
+
{{ t('panels.decision.visualizationHint') }}
|
|
68
75
|
</p>
|
|
69
76
|
</div>
|
|
70
77
|
</template>
|
|
@@ -13,6 +13,7 @@ import StepRestartControl from '~/components/panels/StepRestartControl.vue'
|
|
|
13
13
|
const board = useBoardStore()
|
|
14
14
|
const execution = useExecutionStore()
|
|
15
15
|
const agents = useAgentsStore()
|
|
16
|
+
const { t } = useI18n()
|
|
16
17
|
|
|
17
18
|
// Shared seam contract (open/blockId/close + Escape). No `onOpen` loader: this window reads
|
|
18
19
|
// its data straight off the execution step, so there's nothing to fetch on open.
|
|
@@ -28,6 +29,16 @@ const step = computed(() => {
|
|
|
28
29
|
})
|
|
29
30
|
const meta = computed(() => (step.value ? agents.get(step.value.agentKind) : undefined))
|
|
30
31
|
|
|
32
|
+
const headerLabel = computed(() => meta.value?.label ?? t('panels.structuredResult.fallbackTitle'))
|
|
33
|
+
const headerTitle = computed(() =>
|
|
34
|
+
block.value
|
|
35
|
+
? t('panels.structuredResult.titleWithBlock', {
|
|
36
|
+
label: headerLabel.value,
|
|
37
|
+
title: block.value.title,
|
|
38
|
+
})
|
|
39
|
+
: headerLabel.value,
|
|
40
|
+
)
|
|
41
|
+
|
|
31
42
|
/** The agent's structured JSON, pretty-printed; null when the step produced none. */
|
|
32
43
|
const customJson = computed<string | null>(() => {
|
|
33
44
|
const custom = step.value?.custom
|
|
@@ -59,10 +70,10 @@ const customJson = computed<string | null>(() => {
|
|
|
59
70
|
</span>
|
|
60
71
|
<div class="min-w-0 flex-1">
|
|
61
72
|
<h2 class="truncate text-sm font-semibold text-slate-100">
|
|
62
|
-
{{
|
|
73
|
+
{{ headerTitle }}
|
|
63
74
|
</h2>
|
|
64
75
|
<p class="truncate text-[11px] text-slate-400">
|
|
65
|
-
{{ meta?.description ?? '
|
|
76
|
+
{{ meta?.description ?? t('panels.structuredResult.fallbackDescription') }}
|
|
66
77
|
</p>
|
|
67
78
|
</div>
|
|
68
79
|
<StepRestartControl
|
|
@@ -90,7 +101,7 @@ const customJson = computed<string | null>(() => {
|
|
|
90
101
|
|
|
91
102
|
<template v-if="customJson">
|
|
92
103
|
<h3 class="mb-2 text-[11px] font-semibold uppercase tracking-wide text-slate-500">
|
|
93
|
-
|
|
104
|
+
{{ t('panels.structuredResult.structuredOutput') }}
|
|
94
105
|
</h3>
|
|
95
106
|
<pre
|
|
96
107
|
class="overflow-x-auto rounded-lg border border-slate-800 bg-slate-950/60 p-3 text-[12px] leading-relaxed text-slate-200"
|
|
@@ -102,10 +113,9 @@ const customJson = computed<string | null>(() => {
|
|
|
102
113
|
class="flex h-full flex-col items-center justify-center gap-2 text-center text-slate-400"
|
|
103
114
|
>
|
|
104
115
|
<UIcon name="i-lucide-braces" class="h-8 w-8 opacity-40" />
|
|
105
|
-
<p class="text-sm">
|
|
116
|
+
<p class="text-sm">{{ t('panels.structuredResult.noResult') }}</p>
|
|
106
117
|
<p class="max-w-sm text-[11px] text-slate-500">
|
|
107
|
-
|
|
108
|
-
shows live progress on the board.
|
|
118
|
+
{{ t('panels.structuredResult.noResultHint') }}
|
|
109
119
|
</p>
|
|
110
120
|
</div>
|
|
111
121
|
</div>
|