@cat-factory/app 0.137.2 → 0.138.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/components/followUp/FollowUpWindow.vue +174 -200
- package/app/components/forkDecision/ForkDecisionWindow.vue +250 -275
- package/app/components/gates/GateResultView.vue +309 -333
- package/app/components/humanTest/HumanTestWindow.vue +212 -236
- package/app/components/media/ArtifactLightbox.vue +20 -19
- package/app/components/panels/GenericStructuredResultView.vue +60 -88
- package/app/components/ralph/RalphLoopResultView.vue +150 -171
- package/app/components/testing/TestReportWindow.vue +505 -559
- package/app/components/visualConfirm/VisualConfirmationWindow.vue +224 -262
- package/i18n/locales/de.json +0 -1
- package/i18n/locales/en.json +0 -1
- package/i18n/locales/es.json +0 -1
- package/i18n/locales/fr.json +0 -1
- package/i18n/locales/he.json +0 -1
- package/i18n/locales/it.json +0 -1
- package/i18n/locales/ja.json +0 -1
- package/i18n/locales/pl.json +0 -1
- package/i18n/locales/tr.json +0 -1
- package/i18n/locales/uk.json +0 -1
- package/package.json +1 -1
- package/app/composables/useFocusTrap.ts +0 -72
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// the same seam the requirements / tester windows use.
|
|
9
9
|
import { computed } from 'vue'
|
|
10
10
|
import StepRunMeta from '~/components/panels/StepRunMeta.vue'
|
|
11
|
-
import
|
|
11
|
+
import ResultWindowShell from '~/components/panels/ResultWindowShell.vue'
|
|
12
12
|
import MarkdownProse from '~/components/common/MarkdownProse.vue'
|
|
13
13
|
import CopyButton from '~/components/common/CopyButton.vue'
|
|
14
14
|
|
|
@@ -17,9 +17,12 @@ const execution = useExecutionStore()
|
|
|
17
17
|
const agents = useAgentsStore()
|
|
18
18
|
const { t } = useI18n()
|
|
19
19
|
|
|
20
|
-
// Shared seam contract (open/blockId/close
|
|
21
|
-
//
|
|
22
|
-
|
|
20
|
+
// Shared seam contract (open/blockId/close). No `onOpen` loader: this window reads its data
|
|
21
|
+
// straight off the execution step, so there's nothing to fetch on open. `manageEscape: false`
|
|
22
|
+
// — `ResultWindowShell` owns Escape (and focus trap + scroll lock + stacking).
|
|
23
|
+
const { open, blockId, instanceId, stepIndex, close } = useResultView('generic-structured', {
|
|
24
|
+
manageEscape: false,
|
|
25
|
+
})
|
|
23
26
|
const block = computed(() => (blockId.value ? board.getBlock(blockId.value) : undefined))
|
|
24
27
|
|
|
25
28
|
const instance = computed(() =>
|
|
@@ -54,94 +57,63 @@ const customJson = computed<string | null>(() => {
|
|
|
54
57
|
</script>
|
|
55
58
|
|
|
56
59
|
<template>
|
|
57
|
-
<
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
<div class="min-w-0 flex-1">
|
|
76
|
-
<h2 class="truncate text-sm font-semibold text-slate-100">
|
|
77
|
-
{{ headerTitle }}
|
|
78
|
-
</h2>
|
|
79
|
-
<p class="truncate text-[11px] text-slate-400">
|
|
80
|
-
{{ meta?.description ?? t('panels.structuredResult.fallbackDescription') }}
|
|
81
|
-
</p>
|
|
82
|
-
</div>
|
|
83
|
-
<StepRestartControl
|
|
84
|
-
:instance-id="instanceId"
|
|
85
|
-
:step-index="stepIndex"
|
|
86
|
-
@restarted="close"
|
|
87
|
-
/>
|
|
88
|
-
<button
|
|
89
|
-
class="rounded-md p-1.5 text-slate-400 hover:bg-slate-800 hover:text-slate-200"
|
|
90
|
-
@click="close"
|
|
91
|
-
>
|
|
92
|
-
<UIcon name="i-lucide-x" class="h-4 w-4" />
|
|
93
|
-
</button>
|
|
94
|
-
</header>
|
|
95
|
-
|
|
96
|
-
<div class="flex min-h-0 flex-1">
|
|
97
|
-
<!-- Main: prose summary + structured JSON -->
|
|
98
|
-
<div class="min-w-0 flex-1 overflow-y-auto px-5 py-4">
|
|
99
|
-
<MarkdownProse
|
|
100
|
-
v-if="step?.output"
|
|
101
|
-
:text="step.output"
|
|
102
|
-
class="mb-4 text-[13px] leading-relaxed text-slate-300"
|
|
103
|
-
/>
|
|
60
|
+
<ResultWindowShell
|
|
61
|
+
:open="open"
|
|
62
|
+
:icon="meta?.icon ?? 'i-lucide-braces'"
|
|
63
|
+
icon-class="bg-cyan-500/15 text-cyan-300"
|
|
64
|
+
:title="headerTitle"
|
|
65
|
+
:subtitle="meta?.description ?? t('panels.structuredResult.fallbackDescription')"
|
|
66
|
+
:step-ref="{ instanceId, stepIndex }"
|
|
67
|
+
width="4xl"
|
|
68
|
+
@close="close"
|
|
69
|
+
>
|
|
70
|
+
<div class="flex min-h-0 flex-1">
|
|
71
|
+
<!-- Main: prose summary + structured JSON -->
|
|
72
|
+
<div class="min-w-0 flex-1 overflow-y-auto px-5 py-4">
|
|
73
|
+
<MarkdownProse
|
|
74
|
+
v-if="step?.output"
|
|
75
|
+
:text="step.output"
|
|
76
|
+
class="mb-4 text-[13px] leading-relaxed text-slate-300"
|
|
77
|
+
/>
|
|
104
78
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
</div>
|
|
112
|
-
<pre
|
|
113
|
-
class="overflow-x-auto rounded-lg border border-slate-800 bg-slate-950/60 p-3 text-[12px] leading-relaxed text-slate-200"
|
|
114
|
-
><code>{{ customJson }}</code></pre>
|
|
115
|
-
</template>
|
|
116
|
-
|
|
117
|
-
<div
|
|
118
|
-
v-else-if="!step?.output"
|
|
119
|
-
class="flex h-full flex-col items-center justify-center gap-2 text-center text-slate-400"
|
|
120
|
-
>
|
|
121
|
-
<UIcon name="i-lucide-braces" class="h-8 w-8 opacity-40" />
|
|
122
|
-
<p class="text-sm">{{ t('panels.structuredResult.noResult') }}</p>
|
|
123
|
-
<p class="max-w-sm text-[11px] text-slate-500">
|
|
124
|
-
{{ t('panels.structuredResult.noResultHint') }}
|
|
125
|
-
</p>
|
|
126
|
-
</div>
|
|
79
|
+
<template v-if="customJson">
|
|
80
|
+
<div class="mb-2 flex items-center gap-2">
|
|
81
|
+
<h3 class="text-[11px] font-semibold uppercase tracking-wide text-slate-500">
|
|
82
|
+
{{ t('panels.structuredResult.structuredOutput') }}
|
|
83
|
+
</h3>
|
|
84
|
+
<CopyButton :text="customJson" class="-my-1" />
|
|
127
85
|
</div>
|
|
86
|
+
<pre
|
|
87
|
+
class="overflow-x-auto rounded-lg border border-slate-800 bg-slate-950/60 p-3 text-[12px] leading-relaxed text-slate-200"
|
|
88
|
+
><code>{{ customJson }}</code></pre>
|
|
89
|
+
</template>
|
|
128
90
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
:total-steps="instance?.steps.length"
|
|
139
|
-
:run-failed="instance?.status === 'failed'"
|
|
140
|
-
:failure-at="instance?.failure?.occurredAt"
|
|
141
|
-
/>
|
|
142
|
-
</aside>
|
|
91
|
+
<div
|
|
92
|
+
v-else-if="!step?.output"
|
|
93
|
+
class="flex h-full flex-col items-center justify-center gap-2 text-center text-slate-400"
|
|
94
|
+
>
|
|
95
|
+
<UIcon name="i-lucide-braces" class="h-8 w-8 opacity-40" />
|
|
96
|
+
<p class="text-sm">{{ t('panels.structuredResult.noResult') }}</p>
|
|
97
|
+
<p class="max-w-sm text-[11px] text-slate-500">
|
|
98
|
+
{{ t('panels.structuredResult.noResultHint') }}
|
|
99
|
+
</p>
|
|
143
100
|
</div>
|
|
144
101
|
</div>
|
|
102
|
+
|
|
103
|
+
<!-- Sidebar: shared run metadata + observability rollup -->
|
|
104
|
+
<aside
|
|
105
|
+
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"
|
|
106
|
+
>
|
|
107
|
+
<StepRunMeta
|
|
108
|
+
v-if="step"
|
|
109
|
+
:step="step"
|
|
110
|
+
:instance-id="instanceId ?? undefined"
|
|
111
|
+
:step-number="stepIndex === null ? undefined : stepIndex + 1"
|
|
112
|
+
:total-steps="instance?.steps.length"
|
|
113
|
+
:run-failed="instance?.status === 'failed'"
|
|
114
|
+
:failure-at="instance?.failure?.occurredAt"
|
|
115
|
+
/>
|
|
116
|
+
</aside>
|
|
145
117
|
</div>
|
|
146
|
-
</
|
|
118
|
+
</ResultWindowShell>
|
|
147
119
|
</template>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import { computed } from 'vue'
|
|
8
8
|
import { agentKindMeta } from '~/utils/catalog'
|
|
9
9
|
import type { RalphStepState } from '~/types/execution'
|
|
10
|
-
import
|
|
10
|
+
import ResultWindowShell from '~/components/panels/ResultWindowShell.vue'
|
|
11
11
|
import StepRunMeta from '~/components/panels/StepRunMeta.vue'
|
|
12
12
|
import CopyButton from '~/components/common/CopyButton.vue'
|
|
13
13
|
|
|
@@ -15,8 +15,15 @@ const board = useBoardStore()
|
|
|
15
15
|
const execution = useExecutionStore()
|
|
16
16
|
const { t, d } = useI18n()
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
// `manageEscape: false` — `ResultWindowShell` owns Escape (and focus trap + scroll lock +
|
|
19
|
+
// stacking) via the shared overlay behaviour.
|
|
20
|
+
const { open, blockId, instanceId, stepIndex, close } = useResultView('ralph-loop', {
|
|
21
|
+
manageEscape: false,
|
|
22
|
+
})
|
|
19
23
|
const block = computed(() => (blockId.value ? board.getBlock(blockId.value) : undefined))
|
|
24
|
+
const headerTitle = computed(
|
|
25
|
+
() => `${meta.value.label}${block.value ? ` — ${block.value.title}` : ''}`,
|
|
26
|
+
)
|
|
20
27
|
const prUrl = computed(() => block.value?.pullRequest?.url ?? null)
|
|
21
28
|
|
|
22
29
|
const instance = computed(() =>
|
|
@@ -88,185 +95,157 @@ const STATUS_META = computed<
|
|
|
88
95
|
</script>
|
|
89
96
|
|
|
90
97
|
<template>
|
|
91
|
-
<
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
98
|
+
<ResultWindowShell
|
|
99
|
+
:open="open"
|
|
100
|
+
:icon="meta.icon"
|
|
101
|
+
icon-class="bg-violet-500/15 text-violet-300"
|
|
102
|
+
:title="headerTitle"
|
|
103
|
+
:subtitle="t('ralph.subtitle')"
|
|
104
|
+
:step-ref="{ instanceId, stepIndex }"
|
|
105
|
+
width="3xl"
|
|
106
|
+
testid="ralph-loop-window"
|
|
107
|
+
@close="close"
|
|
108
|
+
>
|
|
109
|
+
<template #header-extras>
|
|
110
|
+
<UBadge
|
|
111
|
+
:color="STATUS_META[status].badge"
|
|
112
|
+
variant="subtle"
|
|
113
|
+
size="sm"
|
|
114
|
+
data-testid="ralph-status"
|
|
102
115
|
>
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
116
|
+
{{ STATUS_META[status].label }}
|
|
117
|
+
</UBadge>
|
|
118
|
+
</template>
|
|
119
|
+
<div class="flex min-h-0 flex-1">
|
|
120
|
+
<div class="min-w-0 flex-1 overflow-y-auto px-5 py-4">
|
|
121
|
+
<div
|
|
122
|
+
v-if="!ralph"
|
|
123
|
+
class="flex h-full flex-col items-center justify-center gap-2 text-center text-slate-400"
|
|
124
|
+
>
|
|
125
|
+
<UIcon :name="meta.icon" class="h-8 w-8 opacity-40" />
|
|
126
|
+
<p class="text-sm">{{ t('ralph.noActivity') }}</p>
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
<template v-else>
|
|
130
|
+
<!-- The completion criterion. -->
|
|
131
|
+
<h3 class="mb-1.5 text-[11px] font-semibold uppercase tracking-wide text-slate-500">
|
|
132
|
+
{{ t('ralph.validationCommand') }}
|
|
133
|
+
</h3>
|
|
134
|
+
<div class="relative rounded-md border border-slate-800 bg-slate-950/60 px-3 py-2">
|
|
135
|
+
<CopyButton :text="ralph.validationCommand" class="absolute end-1 top-1" />
|
|
136
|
+
<code class="block whitespace-pre-wrap pe-8 font-mono text-[12px] text-slate-200">{{
|
|
137
|
+
ralph.validationCommand
|
|
138
|
+
}}</code>
|
|
114
139
|
</div>
|
|
115
|
-
<UBadge
|
|
116
|
-
:color="STATUS_META[status].badge"
|
|
117
|
-
variant="subtle"
|
|
118
|
-
size="sm"
|
|
119
|
-
data-testid="ralph-status"
|
|
120
|
-
>
|
|
121
|
-
{{ STATUS_META[status].label }}
|
|
122
|
-
</UBadge>
|
|
123
|
-
<StepRestartControl
|
|
124
|
-
:instance-id="instanceId"
|
|
125
|
-
:step-index="stepIndex"
|
|
126
|
-
@restarted="close"
|
|
127
|
-
/>
|
|
128
|
-
<button
|
|
129
|
-
class="rounded-md p-1.5 text-slate-400 hover:bg-slate-800 hover:text-slate-200"
|
|
130
|
-
@click="close"
|
|
131
|
-
>
|
|
132
|
-
<UIcon name="i-lucide-x" class="h-4 w-4" />
|
|
133
|
-
</button>
|
|
134
|
-
</header>
|
|
135
140
|
|
|
136
|
-
|
|
137
|
-
<
|
|
138
|
-
<
|
|
139
|
-
|
|
140
|
-
class="flex h-full flex-col items-center justify-center gap-2 text-center text-slate-400"
|
|
141
|
+
<!-- The most recent validation output. -->
|
|
142
|
+
<template v-if="ralph.lastValidationTail">
|
|
143
|
+
<h3
|
|
144
|
+
class="mb-1.5 mt-4 text-[11px] font-semibold uppercase tracking-wide text-slate-500"
|
|
141
145
|
>
|
|
142
|
-
|
|
143
|
-
|
|
146
|
+
{{ t('ralph.lastOutput', { exit: ralph.lastExitCode ?? '?' }) }}
|
|
147
|
+
</h3>
|
|
148
|
+
<div class="relative rounded-md border border-slate-800 bg-slate-950/60 px-3 py-2">
|
|
149
|
+
<CopyButton :text="ralph.lastValidationTail" class="absolute end-1 top-1" />
|
|
150
|
+
<pre
|
|
151
|
+
class="whitespace-pre-wrap pe-8 font-mono text-[11px] leading-relaxed text-slate-400"
|
|
152
|
+
>{{ ralph.lastValidationTail }}</pre
|
|
153
|
+
>
|
|
144
154
|
</div>
|
|
155
|
+
</template>
|
|
145
156
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
</div>
|
|
157
|
-
|
|
158
|
-
<!-- The most recent validation output. -->
|
|
159
|
-
<template v-if="ralph.lastValidationTail">
|
|
160
|
-
<h3
|
|
161
|
-
class="mb-1.5 mt-4 text-[11px] font-semibold uppercase tracking-wide text-slate-500"
|
|
162
|
-
>
|
|
163
|
-
{{ t('ralph.lastOutput', { exit: ralph.lastExitCode ?? '?' }) }}
|
|
164
|
-
</h3>
|
|
165
|
-
<div class="relative rounded-md border border-slate-800 bg-slate-950/60 px-3 py-2">
|
|
166
|
-
<CopyButton :text="ralph.lastValidationTail" class="absolute end-1 top-1" />
|
|
167
|
-
<pre
|
|
168
|
-
class="whitespace-pre-wrap pe-8 font-mono text-[11px] leading-relaxed text-slate-400"
|
|
169
|
-
>{{ ralph.lastValidationTail }}</pre
|
|
170
|
-
>
|
|
171
|
-
</div>
|
|
172
|
-
</template>
|
|
157
|
+
<a
|
|
158
|
+
v-if="prUrl"
|
|
159
|
+
:href="prUrl"
|
|
160
|
+
target="_blank"
|
|
161
|
+
rel="noopener"
|
|
162
|
+
class="mt-3 inline-flex items-center gap-1 text-[12px] text-sky-300 hover:text-sky-200 hover:underline"
|
|
163
|
+
>
|
|
164
|
+
{{ t('ralph.viewPr') }}
|
|
165
|
+
<UIcon name="i-lucide-external-link" class="h-3 w-3" />
|
|
166
|
+
</a>
|
|
173
167
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
168
|
+
<!-- Iteration history: what each pass produced and whether its validation passed. -->
|
|
169
|
+
<section v-if="attempts.length" class="mt-5">
|
|
170
|
+
<h3 class="mb-2 text-[11px] font-semibold uppercase tracking-wide text-slate-500">
|
|
171
|
+
{{ t('ralph.iterationsHeading') }}
|
|
172
|
+
</h3>
|
|
173
|
+
<ol class="space-y-2">
|
|
174
|
+
<li
|
|
175
|
+
v-for="a in attempts"
|
|
176
|
+
:key="a.attempt"
|
|
177
|
+
class="rounded-md border border-slate-800 bg-slate-950/40 px-3 py-2"
|
|
178
|
+
data-testid="ralph-iteration"
|
|
180
179
|
>
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
>
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
</span>
|
|
213
|
-
<span class="ms-auto text-[10px] text-slate-600">{{
|
|
214
|
-
d(new Date(a.at), 'long')
|
|
215
|
-
}}</span>
|
|
216
|
-
</div>
|
|
217
|
-
<p
|
|
218
|
-
v-if="a.summary"
|
|
219
|
-
class="mt-1 whitespace-pre-wrap text-[12px] leading-relaxed text-slate-400"
|
|
220
|
-
>
|
|
221
|
-
{{ a.summary }}
|
|
222
|
-
</p>
|
|
223
|
-
</li>
|
|
224
|
-
</ol>
|
|
225
|
-
</section>
|
|
226
|
-
</template>
|
|
227
|
-
</div>
|
|
180
|
+
<div class="flex items-center gap-2">
|
|
181
|
+
<UIcon
|
|
182
|
+
:name="a.validationPassed ? 'i-lucide-circle-check' : 'i-lucide-circle-x'"
|
|
183
|
+
class="h-3.5 w-3.5"
|
|
184
|
+
:class="a.validationPassed ? 'text-emerald-400' : 'text-rose-400'"
|
|
185
|
+
/>
|
|
186
|
+
<span class="text-[12px] font-medium text-slate-200">
|
|
187
|
+
{{ t('ralph.iteration', { number: a.attempt }) }}
|
|
188
|
+
</span>
|
|
189
|
+
<span class="text-[11px] text-slate-500">
|
|
190
|
+
{{
|
|
191
|
+
a.validationPassed
|
|
192
|
+
? t('ralph.iterationPassed')
|
|
193
|
+
: t('ralph.iterationFailed', { exit: a.exitCode ?? '?' })
|
|
194
|
+
}}
|
|
195
|
+
</span>
|
|
196
|
+
<span class="ms-auto text-[10px] text-slate-600">{{
|
|
197
|
+
d(new Date(a.at), 'long')
|
|
198
|
+
}}</span>
|
|
199
|
+
</div>
|
|
200
|
+
<p
|
|
201
|
+
v-if="a.summary"
|
|
202
|
+
class="mt-1 whitespace-pre-wrap text-[12px] leading-relaxed text-slate-400"
|
|
203
|
+
>
|
|
204
|
+
{{ a.summary }}
|
|
205
|
+
</p>
|
|
206
|
+
</li>
|
|
207
|
+
</ol>
|
|
208
|
+
</section>
|
|
209
|
+
</template>
|
|
210
|
+
</div>
|
|
228
211
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
/>
|
|
242
|
-
<span :class="STATUS_META[status].text">{{ STATUS_META[status].label }}</span>
|
|
243
|
-
</div>
|
|
244
|
-
</div>
|
|
245
|
-
<div v-if="ralph">
|
|
246
|
-
<h4 class="mb-1 text-[11px] font-semibold uppercase tracking-wide text-slate-500">
|
|
247
|
-
{{ t('ralph.sidebar.iterations') }}
|
|
248
|
-
</h4>
|
|
249
|
-
<p class="text-[12px] text-slate-300" data-testid="ralph-iteration-count">
|
|
250
|
-
{{
|
|
251
|
-
t('ralph.sidebar.count', { attempts: ralph.attempts, max: ralph.maxIterations })
|
|
252
|
-
}}
|
|
253
|
-
</p>
|
|
254
|
-
</div>
|
|
255
|
-
<StepRunMeta
|
|
256
|
-
v-if="step"
|
|
257
|
-
:step="step"
|
|
258
|
-
:instance-id="instanceId ?? undefined"
|
|
259
|
-
:step-number="stepIndex === null ? undefined : stepIndex + 1"
|
|
260
|
-
:total-steps="instance?.steps.length"
|
|
261
|
-
:run-failed="instance?.status === 'failed'"
|
|
262
|
-
:failure-at="instance?.failure?.occurredAt"
|
|
212
|
+
<aside
|
|
213
|
+
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"
|
|
214
|
+
>
|
|
215
|
+
<div v-if="ralph">
|
|
216
|
+
<h4 class="mb-2 text-[11px] font-semibold uppercase tracking-wide text-slate-500">
|
|
217
|
+
{{ t('ralph.sidebar.state') }}
|
|
218
|
+
</h4>
|
|
219
|
+
<div class="flex items-center gap-2 text-[13px]">
|
|
220
|
+
<UIcon
|
|
221
|
+
:name="STATUS_META[status].icon"
|
|
222
|
+
class="h-4 w-4"
|
|
223
|
+
:class="STATUS_META[status].text"
|
|
263
224
|
/>
|
|
264
|
-
<
|
|
265
|
-
|
|
266
|
-
</p>
|
|
267
|
-
</aside>
|
|
225
|
+
<span :class="STATUS_META[status].text">{{ STATUS_META[status].label }}</span>
|
|
226
|
+
</div>
|
|
268
227
|
</div>
|
|
269
|
-
|
|
228
|
+
<div v-if="ralph">
|
|
229
|
+
<h4 class="mb-1 text-[11px] font-semibold uppercase tracking-wide text-slate-500">
|
|
230
|
+
{{ t('ralph.sidebar.iterations') }}
|
|
231
|
+
</h4>
|
|
232
|
+
<p class="text-[12px] text-slate-300" data-testid="ralph-iteration-count">
|
|
233
|
+
{{ t('ralph.sidebar.count', { attempts: ralph.attempts, max: ralph.maxIterations }) }}
|
|
234
|
+
</p>
|
|
235
|
+
</div>
|
|
236
|
+
<StepRunMeta
|
|
237
|
+
v-if="step"
|
|
238
|
+
:step="step"
|
|
239
|
+
:instance-id="instanceId ?? undefined"
|
|
240
|
+
:step-number="stepIndex === null ? undefined : stepIndex + 1"
|
|
241
|
+
:total-steps="instance?.steps.length"
|
|
242
|
+
:run-failed="instance?.status === 'failed'"
|
|
243
|
+
:failure-at="instance?.failure?.occurredAt"
|
|
244
|
+
/>
|
|
245
|
+
<p class="mt-auto text-[10px] leading-relaxed text-slate-600">
|
|
246
|
+
{{ t('ralph.sidebar.footer') }}
|
|
247
|
+
</p>
|
|
248
|
+
</aside>
|
|
270
249
|
</div>
|
|
271
|
-
</
|
|
250
|
+
</ResultWindowShell>
|
|
272
251
|
</template>
|