@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
|
@@ -11,6 +11,7 @@ const agentRuns = useAgentRunsStore()
|
|
|
11
11
|
const ui = useUiStore()
|
|
12
12
|
const models = useModelsStore()
|
|
13
13
|
const reviews = useReviewStage()
|
|
14
|
+
const { t } = useI18n()
|
|
14
15
|
|
|
15
16
|
// The async stage this task's iterative reviewer gate (requirements-review / clarity-review)
|
|
16
17
|
// is mid-cycle in (folding the answers, then re-reviewing), or null. While set, the gate is
|
|
@@ -19,11 +20,11 @@ const reviews = useReviewStage()
|
|
|
19
20
|
const reviewStage = computed(() => reviews.stageForBlock(props.block.id))
|
|
20
21
|
const reviewStageLabel = computed(() =>
|
|
21
22
|
reviewStage.value === 'incorporating'
|
|
22
|
-
? '
|
|
23
|
+
? t('inspector.execution.stage.incorporating')
|
|
23
24
|
: reviewStage.value === 'reviewing'
|
|
24
|
-
? '
|
|
25
|
+
? t('inspector.execution.stage.reviewing')
|
|
25
26
|
: reviewStage.value === 'recommending'
|
|
26
|
-
? '
|
|
27
|
+
? t('inspector.execution.stage.recommending')
|
|
27
28
|
: null,
|
|
28
29
|
)
|
|
29
30
|
|
|
@@ -44,14 +45,16 @@ const pr = computed(() => props.block.pullRequest)
|
|
|
44
45
|
const prMerged = computed(() => props.block.status === 'done')
|
|
45
46
|
const prLabel = computed(() => {
|
|
46
47
|
const number = pr.value?.number
|
|
47
|
-
return number
|
|
48
|
+
return number
|
|
49
|
+
? t('inspector.execution.prNumber', { number })
|
|
50
|
+
: t('inspector.execution.pullRequest')
|
|
48
51
|
})
|
|
49
52
|
|
|
50
53
|
const stepLabel: Record<string, string> = {
|
|
51
|
-
pending: '
|
|
52
|
-
working: '
|
|
53
|
-
waiting_decision: '
|
|
54
|
-
done: '
|
|
54
|
+
pending: 'inspector.execution.stepState.pending',
|
|
55
|
+
working: 'inspector.execution.stepState.working',
|
|
56
|
+
waiting_decision: 'inspector.execution.stepState.waiting_decision',
|
|
57
|
+
done: 'inspector.execution.stepState.done',
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
/** A step left mid-flight (`working`) on a failed run gave up — not still working. */
|
|
@@ -68,17 +71,19 @@ function labelForStep(s: {
|
|
|
68
71
|
startingContainer?: boolean
|
|
69
72
|
}) {
|
|
70
73
|
// A step left mid-flight on a failed run reads "Failed", not the misleading "Working".
|
|
71
|
-
if (stepFailed(s)) return '
|
|
74
|
+
if (stepFailed(s)) return t('inspector.execution.failed')
|
|
72
75
|
// A reviewer gate mid-cycle reads its working stage, not "Needs approval".
|
|
73
76
|
if (reviews.isBackground(s.agentKind, props.block.id) && reviewStageLabel.value)
|
|
74
77
|
return reviewStageLabel.value
|
|
75
78
|
// A companion that spent its rework budget needs a decision, not an approval.
|
|
76
|
-
if (s.approval?.status === 'pending' && s.companion?.exceeded)
|
|
77
|
-
|
|
79
|
+
if (s.approval?.status === 'pending' && s.companion?.exceeded)
|
|
80
|
+
return t('inspector.execution.needsDecision')
|
|
81
|
+
if (s.approval?.status === 'pending') return t('inspector.execution.needsApproval')
|
|
78
82
|
// A container-backed step whose container is still cold-booting (only while the
|
|
79
83
|
// run is live — a failed run's mid-flight step is no longer spinning up).
|
|
80
|
-
if (s.startingContainer && !runFailed.value) return '
|
|
81
|
-
|
|
84
|
+
if (s.startingContainer && !runFailed.value) return t('inspector.execution.spinningUp')
|
|
85
|
+
const key = stepLabel[s.state]
|
|
86
|
+
return key ? t(key) : s.state
|
|
82
87
|
}
|
|
83
88
|
|
|
84
89
|
function openDecisionFor(decisionId: string) {
|
|
@@ -138,11 +143,11 @@ async function resetRun() {
|
|
|
138
143
|
size="xs"
|
|
139
144
|
:loading="stopping"
|
|
140
145
|
:disabled="resetting"
|
|
141
|
-
title="
|
|
146
|
+
:title="t('inspector.execution.stopTooltip')"
|
|
142
147
|
data-testid="run-stop"
|
|
143
148
|
@click="stopRun"
|
|
144
149
|
>
|
|
145
|
-
|
|
150
|
+
{{ t('inspector.execution.stop') }}
|
|
146
151
|
</UButton>
|
|
147
152
|
<!-- Destructive: discard the run and return the task to planned. -->
|
|
148
153
|
<UButton
|
|
@@ -152,11 +157,11 @@ async function resetRun() {
|
|
|
152
157
|
size="xs"
|
|
153
158
|
:loading="resetting"
|
|
154
159
|
:disabled="stopping"
|
|
155
|
-
title="
|
|
160
|
+
:title="t('inspector.execution.resetTooltip')"
|
|
156
161
|
data-testid="run-reset"
|
|
157
162
|
@click="resetRun"
|
|
158
163
|
>
|
|
159
|
-
|
|
164
|
+
{{ t('inspector.execution.reset') }}
|
|
160
165
|
</UButton>
|
|
161
166
|
</div>
|
|
162
167
|
</div>
|
|
@@ -173,7 +178,11 @@ async function resetRun() {
|
|
|
173
178
|
<button
|
|
174
179
|
type="button"
|
|
175
180
|
class="flex min-w-0 cursor-pointer items-center gap-2 text-left transition hover:text-white"
|
|
176
|
-
:title="
|
|
181
|
+
:title="
|
|
182
|
+
s.output
|
|
183
|
+
? t('inspector.execution.viewDetailsOutput')
|
|
184
|
+
: t('inspector.execution.viewDetails')
|
|
185
|
+
"
|
|
177
186
|
@click="openStep(i)"
|
|
178
187
|
>
|
|
179
188
|
<UIcon
|
|
@@ -187,9 +196,9 @@ async function resetRun() {
|
|
|
187
196
|
<span
|
|
188
197
|
v-if="isCompanionKind(s.agentKind)"
|
|
189
198
|
class="shrink-0 rounded bg-slate-700/60 px-1 text-[9px] font-medium uppercase tracking-wide text-slate-300"
|
|
190
|
-
title="
|
|
199
|
+
:title="t('inspector.execution.companionTooltip')"
|
|
191
200
|
>
|
|
192
|
-
|
|
201
|
+
{{ t('inspector.execution.companion') }}
|
|
193
202
|
</span>
|
|
194
203
|
<UIcon
|
|
195
204
|
:name="s.output ? 'i-lucide-book-open-text' : 'i-lucide-info'"
|
|
@@ -201,8 +210,15 @@ async function resetRun() {
|
|
|
201
210
|
class="ml-auto font-mono text-[10px] tabular-nums text-slate-300"
|
|
202
211
|
:title="
|
|
203
212
|
s.subtasks.inProgress > 0
|
|
204
|
-
?
|
|
205
|
-
|
|
213
|
+
? t('inspector.execution.subtasksProgress', {
|
|
214
|
+
completed: s.subtasks.completed,
|
|
215
|
+
total: s.subtasks.total,
|
|
216
|
+
inProgress: s.subtasks.inProgress,
|
|
217
|
+
})
|
|
218
|
+
: t('inspector.execution.subtasksDone', {
|
|
219
|
+
completed: s.subtasks.completed,
|
|
220
|
+
total: s.subtasks.total,
|
|
221
|
+
})
|
|
206
222
|
"
|
|
207
223
|
>
|
|
208
224
|
{{ s.subtasks.completed }}/{{ s.subtasks.total }}
|
|
@@ -225,7 +241,7 @@ async function resetRun() {
|
|
|
225
241
|
icon="i-lucide-circle-help"
|
|
226
242
|
@click="openDecisionFor(s.decision.id)"
|
|
227
243
|
>
|
|
228
|
-
|
|
244
|
+
{{ t('inspector.execution.resolve') }}
|
|
229
245
|
</UButton>
|
|
230
246
|
<!-- reviewer gate folding/re-reviewing in the background: a working
|
|
231
247
|
indicator, NOT a "Review" gate (the human is summoned only if needed) -->
|
|
@@ -248,7 +264,7 @@ async function resetRun() {
|
|
|
248
264
|
icon="i-lucide-alert-triangle"
|
|
249
265
|
@click="openApprovalFor(s.approval.id)"
|
|
250
266
|
>
|
|
251
|
-
|
|
267
|
+
{{ t('inspector.execution.decide') }}
|
|
252
268
|
</UButton>
|
|
253
269
|
<UButton
|
|
254
270
|
v-else-if="s.approval && s.approval.status === 'pending'"
|
|
@@ -262,7 +278,11 @@ async function resetRun() {
|
|
|
262
278
|
"
|
|
263
279
|
@click="openApprovalFor(s.approval.id)"
|
|
264
280
|
>
|
|
265
|
-
{{
|
|
281
|
+
{{
|
|
282
|
+
agentKindMeta(s.agentKind).resultView
|
|
283
|
+
? t('inspector.execution.review')
|
|
284
|
+
: t('inspector.execution.approve')
|
|
285
|
+
}}
|
|
266
286
|
</UButton>
|
|
267
287
|
</div>
|
|
268
288
|
<div
|
|
@@ -286,10 +306,20 @@ async function resetRun() {
|
|
|
286
306
|
<div
|
|
287
307
|
v-if="s.selectedFragmentIds && s.selectedFragmentIds.length"
|
|
288
308
|
class="mt-0.5 flex flex-wrap items-center gap-1 pl-6 text-[10px] text-slate-500"
|
|
289
|
-
:title="
|
|
309
|
+
:title="
|
|
310
|
+
t('inspector.execution.fragmentsTooltip', {
|
|
311
|
+
fragments: s.selectedFragmentIds.join(', '),
|
|
312
|
+
})
|
|
313
|
+
"
|
|
290
314
|
>
|
|
291
315
|
<UIcon name="i-lucide-book-marked" class="h-3 w-3 shrink-0" />
|
|
292
|
-
<span>{{
|
|
316
|
+
<span>{{
|
|
317
|
+
t(
|
|
318
|
+
'inspector.execution.standardsApplied',
|
|
319
|
+
{ count: s.selectedFragmentIds.length },
|
|
320
|
+
s.selectedFragmentIds.length,
|
|
321
|
+
)
|
|
322
|
+
}}</span>
|
|
293
323
|
</div>
|
|
294
324
|
<!-- Conditionally-run companion (the Tester's fixer): possible/running/
|
|
295
325
|
completed/skipped, so it's clear whether a fix pass ran. -->
|
|
@@ -306,7 +336,11 @@ async function resetRun() {
|
|
|
306
336
|
]"
|
|
307
337
|
/>
|
|
308
338
|
<span class="text-slate-400">
|
|
309
|
-
{{
|
|
339
|
+
{{
|
|
340
|
+
t('inspector.execution.companionOf', {
|
|
341
|
+
label: agentKindMeta(gateCompanionFor(s, runFailed)!.kind).label,
|
|
342
|
+
})
|
|
343
|
+
}}
|
|
310
344
|
</span>
|
|
311
345
|
<span
|
|
312
346
|
class="ml-auto"
|
|
@@ -325,7 +359,7 @@ async function resetRun() {
|
|
|
325
359
|
<!-- Open PR: link straight to it on GitHub -->
|
|
326
360
|
<div v-if="pr" class="space-y-2">
|
|
327
361
|
<span class="text-[11px] font-semibold uppercase tracking-wide text-slate-400">
|
|
328
|
-
|
|
362
|
+
{{ t('inspector.execution.pullRequest') }}
|
|
329
363
|
</span>
|
|
330
364
|
<UButton
|
|
331
365
|
:to="pr.url"
|
|
@@ -342,7 +376,7 @@ async function resetRun() {
|
|
|
342
376
|
<span class="flex w-full items-center gap-2">
|
|
343
377
|
{{ prLabel }}
|
|
344
378
|
<UBadge :color="prMerged ? 'success' : 'info'" variant="subtle" size="sm" class="ml-auto">
|
|
345
|
-
{{ prMerged ? '
|
|
379
|
+
{{ prMerged ? t('inspector.execution.merged') : t('inspector.execution.open') }}
|
|
346
380
|
</UBadge>
|
|
347
381
|
</span>
|
|
348
382
|
</UButton>
|
|
@@ -362,7 +396,7 @@ async function resetRun() {
|
|
|
362
396
|
block
|
|
363
397
|
@click="execution.mergePr(block.id)"
|
|
364
398
|
>
|
|
365
|
-
|
|
399
|
+
{{ t('inspector.execution.mergePr') }}
|
|
366
400
|
</UButton>
|
|
367
401
|
</div>
|
|
368
402
|
</template>
|
|
@@ -15,6 +15,7 @@ const accounts = useAccountsStore()
|
|
|
15
15
|
const tracker = useTrackerStore()
|
|
16
16
|
const ui = useUiStore()
|
|
17
17
|
const { ready, unavailableInPreset } = useAiReadiness()
|
|
18
|
+
const { t, n } = useI18n()
|
|
18
19
|
|
|
19
20
|
// ---- responsible product person --------------------------------------------
|
|
20
21
|
// The account member (a `product` role-holder) accountable for this task; they are
|
|
@@ -34,7 +35,11 @@ const responsibleLabel = computed(() => {
|
|
|
34
35
|
})
|
|
35
36
|
const responsibleMenu = computed(() => [
|
|
36
37
|
[
|
|
37
|
-
{
|
|
38
|
+
{
|
|
39
|
+
label: t('inspector.runSettings.unassigned'),
|
|
40
|
+
icon: 'i-lucide-user-x',
|
|
41
|
+
onSelect: () => setResponsible(''),
|
|
42
|
+
},
|
|
38
43
|
...productMembers.value.map((m) => ({
|
|
39
44
|
label: m.name || m.email || m.userId,
|
|
40
45
|
icon: 'i-lucide-user',
|
|
@@ -62,8 +67,11 @@ const presetMenu = computed(() => [
|
|
|
62
67
|
[
|
|
63
68
|
{
|
|
64
69
|
label: mergePresets.defaultPreset
|
|
65
|
-
?
|
|
66
|
-
|
|
70
|
+
? t('inspector.runSettings.defaultPresetThresholds', {
|
|
71
|
+
name: mergePresets.defaultPreset.name,
|
|
72
|
+
thresholds: mergePresetThresholds(mergePresets.defaultPreset),
|
|
73
|
+
})
|
|
74
|
+
: t('inspector.runSettings.workspaceDefault'),
|
|
67
75
|
icon: 'i-lucide-rotate-ccw',
|
|
68
76
|
onSelect: () => setPreset(''),
|
|
69
77
|
},
|
|
@@ -99,8 +107,8 @@ const modelPresetMenu = computed(() => [
|
|
|
99
107
|
[
|
|
100
108
|
{
|
|
101
109
|
label: modelPresets.defaultPreset
|
|
102
|
-
?
|
|
103
|
-
: '
|
|
110
|
+
? t('inspector.runSettings.defaultPreset', { name: modelPresets.defaultPreset.name })
|
|
111
|
+
: t('inspector.runSettings.workspaceDefault'),
|
|
104
112
|
icon: 'i-lucide-rotate-ccw',
|
|
105
113
|
onSelect: () => setModelPreset(''),
|
|
106
114
|
},
|
|
@@ -124,7 +132,7 @@ const selectedPipeline = computed(() =>
|
|
|
124
132
|
const pipelineMenu = computed(() => [
|
|
125
133
|
[
|
|
126
134
|
{
|
|
127
|
-
label: '
|
|
135
|
+
label: t('inspector.runSettings.noDefault'),
|
|
128
136
|
icon: 'i-lucide-rotate-ccw',
|
|
129
137
|
onSelect: () => setPipeline(''),
|
|
130
138
|
},
|
|
@@ -151,9 +159,13 @@ function setResolveOnMerge(value: WritebackOverride | null) {
|
|
|
151
159
|
function writebackMenu(set: (value: WritebackOverride | null) => void) {
|
|
152
160
|
return [
|
|
153
161
|
[
|
|
154
|
-
{
|
|
155
|
-
|
|
156
|
-
|
|
162
|
+
{
|
|
163
|
+
label: t('inspector.runSettings.inheritWorkspace'),
|
|
164
|
+
icon: 'i-lucide-rotate-ccw',
|
|
165
|
+
onSelect: () => set(null),
|
|
166
|
+
},
|
|
167
|
+
{ label: t('inspector.runSettings.on'), icon: 'i-lucide-check', onSelect: () => set('on') },
|
|
168
|
+
{ label: t('inspector.runSettings.off'), icon: 'i-lucide-x', onSelect: () => set('off') },
|
|
157
169
|
],
|
|
158
170
|
]
|
|
159
171
|
}
|
|
@@ -162,9 +174,9 @@ function writebackLabel(
|
|
|
162
174
|
override: WritebackOverride | null | undefined,
|
|
163
175
|
wsDefault: boolean,
|
|
164
176
|
): string {
|
|
165
|
-
if (override === 'on') return '
|
|
166
|
-
if (override === 'off') return '
|
|
167
|
-
return
|
|
177
|
+
if (override === 'on') return t('inspector.runSettings.on')
|
|
178
|
+
if (override === 'off') return t('inspector.runSettings.off')
|
|
179
|
+
return wsDefault ? t('inspector.runSettings.inheritOn') : t('inspector.runSettings.inheritOff')
|
|
168
180
|
}
|
|
169
181
|
|
|
170
182
|
const commentOnPrOpenLabel = computed(() =>
|
|
@@ -182,21 +194,29 @@ const resolveOnMergeLabel = computed(() =>
|
|
|
182
194
|
function setTechnical(value: boolean | null) {
|
|
183
195
|
board.updateBlock(props.block.id, { technical: value })
|
|
184
196
|
}
|
|
185
|
-
const technicalMenu = [
|
|
197
|
+
const technicalMenu = computed(() => [
|
|
186
198
|
[
|
|
187
199
|
{
|
|
188
|
-
label: '
|
|
200
|
+
label: t('inspector.runSettings.technical.unset'),
|
|
189
201
|
icon: 'i-lucide-rotate-ccw',
|
|
190
202
|
onSelect: () => setTechnical(null),
|
|
191
203
|
},
|
|
192
|
-
{
|
|
193
|
-
|
|
204
|
+
{
|
|
205
|
+
label: t('inspector.runSettings.technical.technical'),
|
|
206
|
+
icon: 'i-lucide-wrench',
|
|
207
|
+
onSelect: () => setTechnical(true),
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
label: t('inspector.runSettings.technical.business'),
|
|
211
|
+
icon: 'i-lucide-briefcase',
|
|
212
|
+
onSelect: () => setTechnical(false),
|
|
213
|
+
},
|
|
194
214
|
],
|
|
195
|
-
]
|
|
215
|
+
])
|
|
196
216
|
const technicalLabel = computed(() => {
|
|
197
|
-
if (props.block.technical === true) return '
|
|
198
|
-
if (props.block.technical === false) return '
|
|
199
|
-
return '
|
|
217
|
+
if (props.block.technical === true) return t('inspector.runSettings.technical.technical')
|
|
218
|
+
if (props.block.technical === false) return t('inspector.runSettings.technical.business')
|
|
219
|
+
return t('inspector.runSettings.technical.unset')
|
|
200
220
|
})
|
|
201
221
|
</script>
|
|
202
222
|
|
|
@@ -206,7 +226,7 @@ const technicalLabel = computed(() => {
|
|
|
206
226
|
<div>
|
|
207
227
|
<div class="mb-1 flex items-center justify-between">
|
|
208
228
|
<span class="text-[11px] font-semibold uppercase tracking-wide text-slate-400">
|
|
209
|
-
|
|
229
|
+
{{ t('inspector.runSettings.pipeline') }}
|
|
210
230
|
</span>
|
|
211
231
|
<UDropdownMenu :items="pipelineMenu">
|
|
212
232
|
<UButton
|
|
@@ -230,7 +250,7 @@ const technicalLabel = computed(() => {
|
|
|
230
250
|
</UBadge>
|
|
231
251
|
</div>
|
|
232
252
|
<div v-else class="text-[11px] text-slate-500">
|
|
233
|
-
|
|
253
|
+
{{ t('inspector.runSettings.pipelineEmpty') }}
|
|
234
254
|
</div>
|
|
235
255
|
</div>
|
|
236
256
|
|
|
@@ -238,7 +258,7 @@ const technicalLabel = computed(() => {
|
|
|
238
258
|
<div>
|
|
239
259
|
<div class="mb-1 flex items-center justify-between">
|
|
240
260
|
<span class="text-[11px] font-semibold uppercase tracking-wide text-slate-400">
|
|
241
|
-
|
|
261
|
+
{{ t('inspector.runSettings.mergePolicy') }}
|
|
242
262
|
</span>
|
|
243
263
|
<UDropdownMenu :items="presetMenu">
|
|
244
264
|
<UButton
|
|
@@ -251,15 +271,21 @@ const technicalLabel = computed(() => {
|
|
|
251
271
|
</UDropdownMenu>
|
|
252
272
|
</div>
|
|
253
273
|
<div v-if="selectedPreset" class="text-[11px] text-slate-400">
|
|
254
|
-
<
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
274
|
+
<i18n-t keypath="inspector.runSettings.mergePresetDetail" tag="span" scope="global">
|
|
275
|
+
<template #name>
|
|
276
|
+
<span class="text-slate-300">{{ selectedPreset.name }}</span>
|
|
277
|
+
</template>
|
|
278
|
+
<template #complexity>{{ n(selectedPreset.maxComplexity, { key: 'percent' }) }}</template>
|
|
279
|
+
<template #risk>{{ n(selectedPreset.maxRisk, { key: 'percent' }) }}</template>
|
|
280
|
+
<template #impact>{{ n(selectedPreset.maxImpact, { key: 'percent' }) }}</template>
|
|
281
|
+
<template #attempts>{{ selectedPreset.ciMaxAttempts }}</template>
|
|
282
|
+
</i18n-t>
|
|
283
|
+
<span v-if="!block.mergePresetId" class="text-slate-500">{{
|
|
284
|
+
t('inspector.runSettings.workspaceDefaultParen')
|
|
285
|
+
}}</span>
|
|
260
286
|
</div>
|
|
261
287
|
<div v-else class="text-[11px] text-slate-500">
|
|
262
|
-
|
|
288
|
+
{{ t('inspector.runSettings.mergePresetEmpty') }}
|
|
263
289
|
</div>
|
|
264
290
|
</div>
|
|
265
291
|
|
|
@@ -267,7 +293,7 @@ const technicalLabel = computed(() => {
|
|
|
267
293
|
<div>
|
|
268
294
|
<div class="mb-1 flex items-center justify-between">
|
|
269
295
|
<span class="text-[11px] font-semibold uppercase tracking-wide text-slate-400">
|
|
270
|
-
|
|
296
|
+
{{ t('inspector.runSettings.modelPreset') }}
|
|
271
297
|
</span>
|
|
272
298
|
<UDropdownMenu :items="modelPresetMenu">
|
|
273
299
|
<UButton
|
|
@@ -281,14 +307,21 @@ const technicalLabel = computed(() => {
|
|
|
281
307
|
</div>
|
|
282
308
|
<div v-if="selectedModelPreset" class="text-[11px] text-slate-400">
|
|
283
309
|
<span class="text-slate-300">{{ selectedModelPreset.name }}</span>
|
|
284
|
-
|
|
285
|
-
}}<span v-if="Object.keys(selectedModelPreset.overrides).length">
|
|
286
|
-
|
|
310
|
+
{{ t('inspector.runSettings.modelPresetBase', { model: selectedModelPreset.baseModelId })
|
|
311
|
+
}}<span v-if="Object.keys(selectedModelPreset.overrides).length">{{
|
|
312
|
+
t(
|
|
313
|
+
'inspector.runSettings.modelPresetOverrides',
|
|
314
|
+
{ count: Object.keys(selectedModelPreset.overrides).length },
|
|
315
|
+
Object.keys(selectedModelPreset.overrides).length,
|
|
316
|
+
)
|
|
317
|
+
}}</span
|
|
287
318
|
>.
|
|
288
|
-
<span v-if="!block.modelPresetId" class="text-slate-500">
|
|
319
|
+
<span v-if="!block.modelPresetId" class="text-slate-500">{{
|
|
320
|
+
t('inspector.runSettings.workspaceDefaultParen')
|
|
321
|
+
}}</span>
|
|
289
322
|
</div>
|
|
290
323
|
<div v-else class="text-[11px] text-slate-500">
|
|
291
|
-
|
|
324
|
+
{{ t('inspector.runSettings.modelPresetEmpty') }}
|
|
292
325
|
</div>
|
|
293
326
|
<div
|
|
294
327
|
v-if="unavailablePresetModels.length"
|
|
@@ -301,29 +334,31 @@ const technicalLabel = computed(() => {
|
|
|
301
334
|
/>
|
|
302
335
|
<div class="min-w-0">
|
|
303
336
|
<p>
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
337
|
+
<i18n-t keypath="inspector.runSettings.unavailableModels" tag="span" scope="global">
|
|
338
|
+
<template #models>
|
|
339
|
+
<span class="text-amber-100">{{ unavailablePresetModels.join(', ') }}</span>
|
|
340
|
+
</template>
|
|
341
|
+
</i18n-t>
|
|
307
342
|
</p>
|
|
308
343
|
<div class="mt-1.5 flex flex-wrap gap-2">
|
|
309
344
|
<button
|
|
310
345
|
class="font-medium text-amber-100 underline-offset-2 hover:underline"
|
|
311
346
|
@click="ui.openModelConfig()"
|
|
312
347
|
>
|
|
313
|
-
|
|
348
|
+
{{ t('inspector.runSettings.editPresets') }}
|
|
314
349
|
</button>
|
|
315
350
|
<button
|
|
316
351
|
class="font-medium text-amber-100 underline-offset-2 hover:underline"
|
|
317
352
|
@click="ui.openVendorCredentials()"
|
|
318
353
|
>
|
|
319
|
-
|
|
354
|
+
{{ t('inspector.runSettings.configureVendors') }}
|
|
320
355
|
</button>
|
|
321
356
|
</div>
|
|
322
357
|
</div>
|
|
323
358
|
</div>
|
|
324
359
|
</div>
|
|
325
360
|
<p class="mt-1 text-[11px] text-slate-500">
|
|
326
|
-
|
|
361
|
+
{{ t('inspector.runSettings.modelPresetChangeHint') }}
|
|
327
362
|
</p>
|
|
328
363
|
</div>
|
|
329
364
|
|
|
@@ -331,7 +366,7 @@ const technicalLabel = computed(() => {
|
|
|
331
366
|
<div>
|
|
332
367
|
<div class="mb-1 flex items-center justify-between">
|
|
333
368
|
<span class="text-[11px] font-semibold uppercase tracking-wide text-slate-400">
|
|
334
|
-
|
|
369
|
+
{{ t('inspector.runSettings.taskKind') }}
|
|
335
370
|
</span>
|
|
336
371
|
<UDropdownMenu :items="technicalMenu">
|
|
337
372
|
<UButton
|
|
@@ -347,14 +382,13 @@ const technicalLabel = computed(() => {
|
|
|
347
382
|
</div>
|
|
348
383
|
<div class="text-[11px] text-slate-500">
|
|
349
384
|
<template v-if="block.technical === true">
|
|
350
|
-
|
|
351
|
-
regression reference; the spec-writer may produce no business specs.
|
|
385
|
+
{{ t('inspector.runSettings.technicalHint.technical') }}
|
|
352
386
|
</template>
|
|
353
387
|
<template v-else-if="block.technical === false">
|
|
354
|
-
|
|
388
|
+
{{ t('inspector.runSettings.technicalHint.business') }}
|
|
355
389
|
</template>
|
|
356
390
|
<template v-else>
|
|
357
|
-
|
|
391
|
+
{{ t('inspector.runSettings.technicalHint.unset') }}
|
|
358
392
|
</template>
|
|
359
393
|
</div>
|
|
360
394
|
</div>
|
|
@@ -363,12 +397,14 @@ const technicalLabel = computed(() => {
|
|
|
363
397
|
<div>
|
|
364
398
|
<div class="mb-1 flex items-center justify-between">
|
|
365
399
|
<span class="text-[11px] font-semibold uppercase tracking-wide text-slate-400">
|
|
366
|
-
|
|
400
|
+
{{ t('inspector.runSettings.issueWriteback') }}
|
|
367
401
|
</span>
|
|
368
402
|
</div>
|
|
369
403
|
<div class="space-y-1.5">
|
|
370
404
|
<div class="flex items-center justify-between">
|
|
371
|
-
<span class="text-[11px] text-slate-400">
|
|
405
|
+
<span class="text-[11px] text-slate-400">{{
|
|
406
|
+
t('inspector.runSettings.commentOnPrOpen')
|
|
407
|
+
}}</span>
|
|
372
408
|
<UDropdownMenu :items="writebackMenu(setCommentOnPrOpen)">
|
|
373
409
|
<UButton
|
|
374
410
|
size="xs"
|
|
@@ -381,7 +417,9 @@ const technicalLabel = computed(() => {
|
|
|
381
417
|
</UDropdownMenu>
|
|
382
418
|
</div>
|
|
383
419
|
<div class="flex items-center justify-between">
|
|
384
|
-
<span class="text-[11px] text-slate-400">
|
|
420
|
+
<span class="text-[11px] text-slate-400">{{
|
|
421
|
+
t('inspector.runSettings.closeOnMerge')
|
|
422
|
+
}}</span>
|
|
385
423
|
<UDropdownMenu :items="writebackMenu(setResolveOnMerge)">
|
|
386
424
|
<UButton
|
|
387
425
|
size="xs"
|
|
@@ -395,7 +433,7 @@ const technicalLabel = computed(() => {
|
|
|
395
433
|
</div>
|
|
396
434
|
</div>
|
|
397
435
|
<div class="mt-1 text-[11px] text-slate-500">
|
|
398
|
-
|
|
436
|
+
{{ t('inspector.runSettings.writebackHint') }}
|
|
399
437
|
</div>
|
|
400
438
|
</div>
|
|
401
439
|
|
|
@@ -403,7 +441,7 @@ const technicalLabel = computed(() => {
|
|
|
403
441
|
<div>
|
|
404
442
|
<div class="mb-1 flex items-center justify-between">
|
|
405
443
|
<span class="text-[11px] font-semibold uppercase tracking-wide text-slate-400">
|
|
406
|
-
|
|
444
|
+
{{ t('inspector.runSettings.responsibleProduct') }}
|
|
407
445
|
</span>
|
|
408
446
|
<UDropdownMenu :items="responsibleMenu">
|
|
409
447
|
<UButton
|
|
@@ -427,7 +465,7 @@ const technicalLabel = computed(() => {
|
|
|
427
465
|
</UBadge>
|
|
428
466
|
</div>
|
|
429
467
|
<div v-else class="text-[11px] text-slate-500">
|
|
430
|
-
|
|
468
|
+
{{ t('inspector.runSettings.responsibleEmpty') }}
|
|
431
469
|
</div>
|
|
432
470
|
</div>
|
|
433
471
|
|
|
@@ -435,7 +473,7 @@ const technicalLabel = computed(() => {
|
|
|
435
473
|
<div>
|
|
436
474
|
<div class="flex items-center justify-between gap-2">
|
|
437
475
|
<span class="text-[11px] font-semibold uppercase tracking-wide text-slate-400">
|
|
438
|
-
|
|
476
|
+
{{ t('inspector.runSettings.autoStartDependents') }}
|
|
439
477
|
</span>
|
|
440
478
|
<USwitch
|
|
441
479
|
size="sm"
|
|
@@ -444,8 +482,7 @@ const technicalLabel = computed(() => {
|
|
|
444
482
|
/>
|
|
445
483
|
</div>
|
|
446
484
|
<div class="mt-1 text-[11px] text-slate-500">
|
|
447
|
-
|
|
448
|
-
dependencies are also done).
|
|
485
|
+
{{ t('inspector.runSettings.autoStartHint') }}
|
|
449
486
|
</div>
|
|
450
487
|
</div>
|
|
451
488
|
</div>
|
|
@@ -5,6 +5,7 @@ const props = defineProps<{ block: Block }>()
|
|
|
5
5
|
|
|
6
6
|
const board = useBoardStore()
|
|
7
7
|
const fragments = useFragmentsStore()
|
|
8
|
+
const { t } = useI18n()
|
|
8
9
|
|
|
9
10
|
// ---- best-practice prompt fragments ----------------------------------------
|
|
10
11
|
// Selected fragments (resolved against the catalog; unknown ids are dropped).
|
|
@@ -47,13 +48,13 @@ function removeFragment(id: string) {
|
|
|
47
48
|
<!-- module assignment -->
|
|
48
49
|
<div>
|
|
49
50
|
<div class="mb-1 text-[11px] font-semibold uppercase tracking-wide text-slate-400">
|
|
50
|
-
|
|
51
|
+
{{ t('inspector.structure.module') }}
|
|
51
52
|
</div>
|
|
52
53
|
<UInput
|
|
53
54
|
v-model="block.moduleName"
|
|
54
55
|
size="sm"
|
|
55
56
|
class="w-full"
|
|
56
|
-
placeholder="
|
|
57
|
+
:placeholder="t('inspector.structure.modulePlaceholder')"
|
|
57
58
|
icon="i-lucide-package"
|
|
58
59
|
/>
|
|
59
60
|
</div>
|
|
@@ -62,7 +63,7 @@ function removeFragment(id: string) {
|
|
|
62
63
|
<div>
|
|
63
64
|
<div class="mb-1 flex items-center justify-between">
|
|
64
65
|
<span class="text-[11px] font-semibold uppercase tracking-wide text-slate-400">
|
|
65
|
-
|
|
66
|
+
{{ t('inspector.structure.bestPractices') }}
|
|
66
67
|
</span>
|
|
67
68
|
<UDropdownMenu v-if="fragmentMenu.length" :items="fragmentMenu">
|
|
68
69
|
<UButton
|
|
@@ -89,7 +90,7 @@ function removeFragment(id: string) {
|
|
|
89
90
|
</UBadge>
|
|
90
91
|
</div>
|
|
91
92
|
<div v-else class="text-[11px] text-slate-500">
|
|
92
|
-
|
|
93
|
+
{{ t('inspector.structure.bestPracticesEmpty') }}
|
|
93
94
|
</div>
|
|
94
95
|
</div>
|
|
95
96
|
</div>
|