@cat-factory/app 0.61.0 → 0.62.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/sandbox/SandboxPanel.vue +6 -5
- package/app/components/settings/KubernetesEngineForm.vue +7 -4
- package/app/components/settings/KubernetesEnvironmentForm.vue +8 -4
- package/app/components/settings/MergePresetHealthModal.vue +166 -0
- package/app/components/settings/MergeThresholdsPanel.vue +22 -1
- package/app/composables/api/presets.ts +6 -0
- package/app/composables/useMergePresetHealth.ts +65 -0
- package/app/pages/index.vue +17 -0
- package/app/stores/mergePresets.ts +33 -2
- package/app/stores/ui.ts +26 -0
- package/app/stores/workspace.ts +4 -1
- package/app/utils/mergePreset.ts +2 -0
- package/i18n/locales/en.json +23 -1
- package/i18n/locales/es.json +24 -2
- package/i18n/locales/fr.json +24 -2
- package/i18n/locales/he.json +24 -2
- package/i18n/locales/ja.json +24 -2
- package/i18n/locales/pl.json +24 -2
- package/i18n/locales/tr.json +24 -2
- package/i18n/locales/uk.json +24 -2
- package/package.json +2 -2
|
@@ -61,13 +61,14 @@ const name = ref('')
|
|
|
61
61
|
const selectedPromptIds = ref<string[]>([])
|
|
62
62
|
const selectedModelIds = ref<string[]>([])
|
|
63
63
|
const selectedFixtureIds = ref<string[]>([])
|
|
64
|
-
// The judge model.
|
|
64
|
+
// The judge model. 'default' = the deployment's routing default (resolved server-side);
|
|
65
65
|
// picking one explicitly is the recourse on a deployment that has no default model wired,
|
|
66
|
-
// where leaving it on default makes every run fail at create time.
|
|
67
|
-
|
|
66
|
+
// where leaving it on default makes every run fail at create time. ('default' is a non-empty
|
|
67
|
+
// sentinel because reka-ui's SelectItem reserves the empty string to clear a selection.)
|
|
68
|
+
const selectedJudgeModel = ref<string>('default')
|
|
68
69
|
|
|
69
70
|
const judgeModelItems = computed(() => [
|
|
70
|
-
{ label: t('sandbox.deploymentDefault'), value: '' },
|
|
71
|
+
{ label: t('sandbox.deploymentDefault'), value: 'default' },
|
|
71
72
|
...store.selectableModels.map((m) => ({ label: m.label, value: m.id })),
|
|
72
73
|
])
|
|
73
74
|
|
|
@@ -112,7 +113,7 @@ async function createAndRun() {
|
|
|
112
113
|
const created = await store.createExperiment({
|
|
113
114
|
name: name.value.trim() || t('sandbox.defaultRunName', { kind: agentKind.value }),
|
|
114
115
|
agentKind: agentKind.value,
|
|
115
|
-
judgeModel: selectedJudgeModel.value
|
|
116
|
+
judgeModel: selectedJudgeModel.value === 'default' ? undefined : selectedJudgeModel.value,
|
|
116
117
|
matrix: {
|
|
117
118
|
promptVersionIds: selectedPromptIds.value,
|
|
118
119
|
models: selectedModelIds.value,
|
|
@@ -60,7 +60,10 @@ const form = reactive({
|
|
|
60
60
|
servicePort: '',
|
|
61
61
|
gatewayName: '',
|
|
62
62
|
httpRouteName: '',
|
|
63
|
-
|
|
63
|
+
// 'default' is a non-empty sentinel for "let the apiserver/derivation decide the scheme":
|
|
64
|
+
// reka-ui's SelectItem reserves the empty string to clear a selection, so it can't be an
|
|
65
|
+
// option value. buildUrl() omits `scheme` entirely when this is 'default'.
|
|
66
|
+
urlScheme: 'default' as 'default' | 'http' | 'https',
|
|
64
67
|
})
|
|
65
68
|
const apiToken = ref('')
|
|
66
69
|
|
|
@@ -78,7 +81,7 @@ const urlSourceItems = computed(() => [
|
|
|
78
81
|
},
|
|
79
82
|
])
|
|
80
83
|
const schemeItems = computed(() => [
|
|
81
|
-
{ label: t('settings.infrastructure.kubernetesEngine.schemeDefault'), value: '' },
|
|
84
|
+
{ label: t('settings.infrastructure.kubernetesEngine.schemeDefault'), value: 'default' },
|
|
82
85
|
{ label: 'https', value: 'https' },
|
|
83
86
|
{ label: 'http', value: 'http' },
|
|
84
87
|
])
|
|
@@ -107,7 +110,7 @@ watch(
|
|
|
107
110
|
form.servicePort = typeof url?.port === 'number' ? String(url.port) : ''
|
|
108
111
|
form.gatewayName = typeof url?.gatewayName === 'string' ? url.gatewayName : ''
|
|
109
112
|
form.httpRouteName = typeof url?.httpRouteName === 'string' ? url.httpRouteName : ''
|
|
110
|
-
|
|
113
|
+
form.urlScheme = url?.scheme === 'http' || url?.scheme === 'https' ? url.scheme : 'default'
|
|
111
114
|
},
|
|
112
115
|
{ immediate: true },
|
|
113
116
|
)
|
|
@@ -145,7 +148,7 @@ function buildUrl(): Record<string, unknown> {
|
|
|
145
148
|
} else {
|
|
146
149
|
if (form.httpRouteName.trim()) url.httpRouteName = form.httpRouteName.trim()
|
|
147
150
|
}
|
|
148
|
-
if (form.urlScheme) url.scheme = form.urlScheme
|
|
151
|
+
if (form.urlScheme !== 'default') url.scheme = form.urlScheme
|
|
149
152
|
return url
|
|
150
153
|
}
|
|
151
154
|
|
|
@@ -43,7 +43,10 @@ const form = reactive({
|
|
|
43
43
|
ingressName: '',
|
|
44
44
|
serviceName: '',
|
|
45
45
|
servicePort: '',
|
|
46
|
-
|
|
46
|
+
// 'default' is a non-empty sentinel for "let the apiserver/derivation decide the scheme":
|
|
47
|
+
// reka-ui's SelectItem reserves the empty string to clear a selection, so it can't be an
|
|
48
|
+
// option value. The url builder omits `scheme` entirely when this is 'default'.
|
|
49
|
+
urlScheme: 'default' as 'default' | 'http' | 'https',
|
|
47
50
|
})
|
|
48
51
|
const apiToken = ref('')
|
|
49
52
|
|
|
@@ -66,7 +69,7 @@ const urlSourceItems = computed(() => [
|
|
|
66
69
|
},
|
|
67
70
|
])
|
|
68
71
|
const schemeItems = computed(() => [
|
|
69
|
-
{ label: t('settings.providerConnection.kubernetesEnv.schemeDefault'), value: '' },
|
|
72
|
+
{ label: t('settings.providerConnection.kubernetesEnv.schemeDefault'), value: 'default' },
|
|
70
73
|
{ label: 'https', value: 'https' },
|
|
71
74
|
{ label: 'http', value: 'http' },
|
|
72
75
|
])
|
|
@@ -111,7 +114,8 @@ watch(
|
|
|
111
114
|
form.serviceName = typeof url.serviceName === 'string' ? url.serviceName : ''
|
|
112
115
|
form.servicePort = typeof url.port === 'number' ? String(url.port) : ''
|
|
113
116
|
}
|
|
114
|
-
|
|
117
|
+
form.urlScheme =
|
|
118
|
+
url && (url.scheme === 'http' || url.scheme === 'https') ? url.scheme : 'default'
|
|
115
119
|
},
|
|
116
120
|
{ immediate: true },
|
|
117
121
|
)
|
|
@@ -171,7 +175,7 @@ function buildUrl(): Record<string, unknown> {
|
|
|
171
175
|
const port = Number(form.servicePort)
|
|
172
176
|
if (form.servicePort.trim() && Number.isInteger(port)) url.port = port
|
|
173
177
|
}
|
|
174
|
-
if (form.urlScheme) url.scheme = form.urlScheme
|
|
178
|
+
if (form.urlScheme !== 'default') url.scheme = form.urlScheme
|
|
175
179
|
return url
|
|
176
180
|
}
|
|
177
181
|
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// Startup advisory for built-in merge presets that drifted from the catalog. Opened once per
|
|
3
|
+
// session from the board page when `useMergePresetHealth` reports any issue. Lists:
|
|
4
|
+
// • new built-in presets the workspace doesn't have yet (ADD them);
|
|
5
|
+
// • built-ins with a newer catalog version available (RESEED to adopt it).
|
|
6
|
+
// Both fixes are the same reseed call (it creates or updates by catalog id). Detection is
|
|
7
|
+
// client-side (see useMergePresetHealth); the actions hit the mergePresets store.
|
|
8
|
+
const { t } = useI18n()
|
|
9
|
+
const ui = useUiStore()
|
|
10
|
+
const presets = useMergePresetsStore()
|
|
11
|
+
const { newPresets, outdated, hasIssues } = useMergePresetHealth()
|
|
12
|
+
const toast = useToast()
|
|
13
|
+
|
|
14
|
+
const open = computed({
|
|
15
|
+
get: () => ui.mergePresetHealthOpen,
|
|
16
|
+
set: (v: boolean) => {
|
|
17
|
+
if (!v) ui.closeMergePresetHealth()
|
|
18
|
+
},
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
// Per-preset in-flight ids, so each row's button shows its own spinner.
|
|
22
|
+
const busy = ref<Set<string>>(new Set())
|
|
23
|
+
const isBusy = (id: string) => busy.value.has(id)
|
|
24
|
+
const anyBusy = computed(() => busy.value.size > 0)
|
|
25
|
+
|
|
26
|
+
async function reseed(id: string) {
|
|
27
|
+
busy.value = new Set(busy.value).add(id)
|
|
28
|
+
try {
|
|
29
|
+
await presets.reseed(id)
|
|
30
|
+
} catch (e) {
|
|
31
|
+
toast.add({
|
|
32
|
+
title: t('mergePreset.health.toast.reseedFailed'),
|
|
33
|
+
description: e instanceof Error ? e.message : String(e),
|
|
34
|
+
icon: 'i-lucide-triangle-alert',
|
|
35
|
+
color: 'error',
|
|
36
|
+
})
|
|
37
|
+
} finally {
|
|
38
|
+
const next = new Set(busy.value)
|
|
39
|
+
next.delete(id)
|
|
40
|
+
busy.value = next
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Reseed every advised preset (new + outdated built-ins) in one go. */
|
|
45
|
+
async function reseedAll() {
|
|
46
|
+
const ids = [...newPresets.value, ...outdated.value].map((i) => i.id)
|
|
47
|
+
for (const id of new Set(ids)) await reseed(id)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const reseedableCount = computed(
|
|
51
|
+
() => new Set([...newPresets.value, ...outdated.value].map((i) => i.id)).size,
|
|
52
|
+
)
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<template>
|
|
56
|
+
<UModal v-model:open="open" :title="t('mergePreset.health.title')" :ui="{ content: 'max-w-2xl' }">
|
|
57
|
+
<template #body>
|
|
58
|
+
<div v-if="!hasIssues" class="py-6 text-center text-sm text-slate-400">
|
|
59
|
+
<UIcon name="i-lucide-check-circle-2" class="mx-auto mb-2 h-8 w-8 text-emerald-400" />
|
|
60
|
+
{{ t('mergePreset.health.allValid') }}
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<div v-else class="space-y-5">
|
|
64
|
+
<!-- New built-in presets the workspace can add. -->
|
|
65
|
+
<section v-if="newPresets.length" class="space-y-2">
|
|
66
|
+
<div class="flex items-center gap-2">
|
|
67
|
+
<UIcon name="i-lucide-sparkles" class="h-4 w-4 text-emerald-400" />
|
|
68
|
+
<h3 class="text-sm font-semibold text-slate-200">
|
|
69
|
+
{{ t('mergePreset.health.newHeading') }}
|
|
70
|
+
</h3>
|
|
71
|
+
</div>
|
|
72
|
+
<p class="text-[11px] text-slate-500">{{ t('mergePreset.health.newDescription') }}</p>
|
|
73
|
+
<ul class="space-y-2">
|
|
74
|
+
<li
|
|
75
|
+
v-for="i in newPresets"
|
|
76
|
+
:key="i.id"
|
|
77
|
+
class="flex items-center justify-between gap-3 rounded-lg border border-slate-800 bg-slate-900/40 p-3"
|
|
78
|
+
>
|
|
79
|
+
<div class="min-w-0">
|
|
80
|
+
<span class="truncate text-sm font-medium text-slate-100 capitalize">{{
|
|
81
|
+
i.name
|
|
82
|
+
}}</span>
|
|
83
|
+
</div>
|
|
84
|
+
<UButton
|
|
85
|
+
size="xs"
|
|
86
|
+
color="primary"
|
|
87
|
+
variant="subtle"
|
|
88
|
+
icon="i-lucide-plus"
|
|
89
|
+
:loading="isBusy(i.id)"
|
|
90
|
+
:disabled="anyBusy"
|
|
91
|
+
@click="reseed(i.id)"
|
|
92
|
+
>
|
|
93
|
+
{{ t('mergePreset.health.add') }}
|
|
94
|
+
</UButton>
|
|
95
|
+
</li>
|
|
96
|
+
</ul>
|
|
97
|
+
</section>
|
|
98
|
+
|
|
99
|
+
<!-- Outdated built-ins: a newer catalog version is available. -->
|
|
100
|
+
<section v-if="outdated.length" class="space-y-2">
|
|
101
|
+
<div class="flex items-center gap-2">
|
|
102
|
+
<UIcon name="i-lucide-arrow-up-circle" class="h-4 w-4 text-amber-400" />
|
|
103
|
+
<h3 class="text-sm font-semibold text-slate-200">
|
|
104
|
+
{{ t('mergePreset.health.updatesHeading') }}
|
|
105
|
+
</h3>
|
|
106
|
+
</div>
|
|
107
|
+
<p class="text-[11px] text-slate-500">{{ t('mergePreset.health.updatesDescription') }}</p>
|
|
108
|
+
<ul class="space-y-2">
|
|
109
|
+
<li
|
|
110
|
+
v-for="i in outdated"
|
|
111
|
+
:key="i.id"
|
|
112
|
+
class="flex items-center justify-between gap-3 rounded-lg border border-slate-800 bg-slate-900/40 p-3"
|
|
113
|
+
>
|
|
114
|
+
<div class="min-w-0">
|
|
115
|
+
<span class="truncate text-sm font-medium text-slate-100">{{ i.name }}</span>
|
|
116
|
+
<p class="text-[11px] text-amber-400/80">
|
|
117
|
+
{{
|
|
118
|
+
t('mergePreset.health.versionAvailable', {
|
|
119
|
+
from: i.fromVersion ?? 0,
|
|
120
|
+
to: i.toVersion ?? 0,
|
|
121
|
+
})
|
|
122
|
+
}}
|
|
123
|
+
</p>
|
|
124
|
+
</div>
|
|
125
|
+
<UButton
|
|
126
|
+
size="xs"
|
|
127
|
+
color="primary"
|
|
128
|
+
variant="subtle"
|
|
129
|
+
icon="i-lucide-rotate-ccw"
|
|
130
|
+
:loading="isBusy(i.id)"
|
|
131
|
+
:disabled="anyBusy"
|
|
132
|
+
@click="reseed(i.id)"
|
|
133
|
+
>
|
|
134
|
+
{{ t('mergePreset.health.reseed') }}
|
|
135
|
+
</UButton>
|
|
136
|
+
</li>
|
|
137
|
+
</ul>
|
|
138
|
+
</section>
|
|
139
|
+
</div>
|
|
140
|
+
</template>
|
|
141
|
+
|
|
142
|
+
<template #footer>
|
|
143
|
+
<div class="flex w-full items-center justify-between gap-2">
|
|
144
|
+
<UButton
|
|
145
|
+
v-if="reseedableCount > 1"
|
|
146
|
+
color="primary"
|
|
147
|
+
variant="ghost"
|
|
148
|
+
icon="i-lucide-rotate-ccw"
|
|
149
|
+
:loading="anyBusy"
|
|
150
|
+
@click="reseedAll"
|
|
151
|
+
>
|
|
152
|
+
{{ t('mergePreset.health.reseedAll', { count: reseedableCount }) }}
|
|
153
|
+
</UButton>
|
|
154
|
+
<span v-else />
|
|
155
|
+
<UButton
|
|
156
|
+
color="neutral"
|
|
157
|
+
variant="ghost"
|
|
158
|
+
:disabled="anyBusy"
|
|
159
|
+
@click="ui.closeMergePresetHealth()"
|
|
160
|
+
>
|
|
161
|
+
{{ hasIssues ? t('mergePreset.health.dismiss') : t('mergePreset.health.done') }}
|
|
162
|
+
</UButton>
|
|
163
|
+
</div>
|
|
164
|
+
</template>
|
|
165
|
+
</UModal>
|
|
166
|
+
</template>
|
|
@@ -40,6 +40,7 @@ interface Draft {
|
|
|
40
40
|
ciMaxAttempts: number
|
|
41
41
|
maxRequirementIterations: number
|
|
42
42
|
maxRequirementConcernAllowed: RequirementConcernLevel
|
|
43
|
+
autoMergeEnabled: boolean
|
|
43
44
|
}
|
|
44
45
|
const drafts = reactive<Record<string, Draft>>({})
|
|
45
46
|
|
|
@@ -52,6 +53,7 @@ function toDraft(p: MergeThresholdPreset): Draft {
|
|
|
52
53
|
ciMaxAttempts: p.ciMaxAttempts,
|
|
53
54
|
maxRequirementIterations: p.maxRequirementIterations,
|
|
54
55
|
maxRequirementConcernAllowed: p.maxRequirementConcernAllowed,
|
|
56
|
+
autoMergeEnabled: p.autoMergeEnabled,
|
|
55
57
|
}
|
|
56
58
|
}
|
|
57
59
|
|
|
@@ -88,6 +90,7 @@ async function save(p: MergeThresholdPreset) {
|
|
|
88
90
|
ciMaxAttempts: d.ciMaxAttempts,
|
|
89
91
|
maxRequirementIterations: d.maxRequirementIterations,
|
|
90
92
|
maxRequirementConcernAllowed: d.maxRequirementConcernAllowed,
|
|
93
|
+
autoMergeEnabled: d.autoMergeEnabled,
|
|
91
94
|
})
|
|
92
95
|
toast.add({
|
|
93
96
|
title: t('settings.mergeThresholds.toast.saved'),
|
|
@@ -133,6 +136,7 @@ const draft = reactive<Draft>({
|
|
|
133
136
|
ciMaxAttempts: 10,
|
|
134
137
|
maxRequirementIterations: 6,
|
|
135
138
|
maxRequirementConcernAllowed: 'none',
|
|
139
|
+
autoMergeEnabled: true,
|
|
136
140
|
})
|
|
137
141
|
|
|
138
142
|
async function create() {
|
|
@@ -147,8 +151,10 @@ async function create() {
|
|
|
147
151
|
ciMaxAttempts: draft.ciMaxAttempts,
|
|
148
152
|
maxRequirementIterations: draft.maxRequirementIterations,
|
|
149
153
|
maxRequirementConcernAllowed: draft.maxRequirementConcernAllowed,
|
|
154
|
+
autoMergeEnabled: draft.autoMergeEnabled,
|
|
150
155
|
})
|
|
151
156
|
draft.name = ''
|
|
157
|
+
draft.autoMergeEnabled = true
|
|
152
158
|
toast.add({
|
|
153
159
|
title: t('settings.mergeThresholds.toast.created'),
|
|
154
160
|
icon: 'i-lucide-check',
|
|
@@ -290,7 +296,17 @@ async function create() {
|
|
|
290
296
|
</label>
|
|
291
297
|
</div>
|
|
292
298
|
|
|
293
|
-
<div class="mt-3 flex justify-
|
|
299
|
+
<div class="mt-3 flex items-center justify-between gap-3">
|
|
300
|
+
<USwitch
|
|
301
|
+
v-model="drafts[p.id]!.autoMergeEnabled"
|
|
302
|
+
size="sm"
|
|
303
|
+
:label="t('settings.mergeThresholds.field.autoMerge')"
|
|
304
|
+
:description="
|
|
305
|
+
drafts[p.id]!.autoMergeEnabled
|
|
306
|
+
? t('settings.mergeThresholds.autoMergeOnHint')
|
|
307
|
+
: t('settings.mergeThresholds.autoMergeOffHint')
|
|
308
|
+
"
|
|
309
|
+
/>
|
|
294
310
|
<UButton
|
|
295
311
|
color="primary"
|
|
296
312
|
variant="soft"
|
|
@@ -373,6 +389,11 @@ async function create() {
|
|
|
373
389
|
size="sm"
|
|
374
390
|
/>
|
|
375
391
|
</label>
|
|
392
|
+
<USwitch
|
|
393
|
+
v-model="draft.autoMergeEnabled"
|
|
394
|
+
size="sm"
|
|
395
|
+
:label="t('settings.mergeThresholds.field.autoMerge')"
|
|
396
|
+
/>
|
|
376
397
|
<UButton
|
|
377
398
|
color="primary"
|
|
378
399
|
size="sm"
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
deleteModelPresetContract,
|
|
6
6
|
listMergePresetsContract,
|
|
7
7
|
listModelPresetsContract,
|
|
8
|
+
reseedMergePresetContract,
|
|
8
9
|
updateMergePresetContract,
|
|
9
10
|
updateModelPresetContract,
|
|
10
11
|
} from '@cat-factory/contracts'
|
|
@@ -38,6 +39,11 @@ export function presetsApi({ send, ws }: ApiContext) {
|
|
|
38
39
|
deleteMergePreset: (workspaceId: string, presetId: string) =>
|
|
39
40
|
send(deleteMergePresetContract, { pathPrefix: ws(workspaceId), pathParams: { presetId } }),
|
|
40
41
|
|
|
42
|
+
// Restore a built-in preset to its current catalog definition (adopt an update, repair a
|
|
43
|
+
// drifted one, or materialise a new built-in that appeared). Custom presets reject this.
|
|
44
|
+
reseedMergePreset: (workspaceId: string, presetId: string) =>
|
|
45
|
+
send(reseedMergePresetContract, { pathPrefix: ws(workspaceId), pathParams: { presetId } }),
|
|
46
|
+
|
|
41
47
|
// ---- model presets (per-task model->agent mapping library) ------------
|
|
42
48
|
listModelPresets: (workspaceId: string) =>
|
|
43
49
|
send(listModelPresetsContract, { pathPrefix: ws(workspaceId) }),
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { computed } from 'vue'
|
|
2
|
+
import type { MergeThresholdPreset } from '~/types/merge'
|
|
3
|
+
import { useMergePresetsStore } from '~/stores/mergePresets'
|
|
4
|
+
|
|
5
|
+
export type MergePresetIssueType = 'outdated' | 'new'
|
|
6
|
+
|
|
7
|
+
/** A built-in merge preset that the workspace should reseed (an update, or a new one to add). */
|
|
8
|
+
export interface MergePresetIssue {
|
|
9
|
+
type: MergePresetIssueType
|
|
10
|
+
/** The catalog (built-in) id — what the reseed endpoint is keyed by. */
|
|
11
|
+
id: string
|
|
12
|
+
/** The preset name (the stored copy's for `outdated`, the built-in id for a `new` one). */
|
|
13
|
+
name: string
|
|
14
|
+
/** For an `outdated` issue: the persisted copy's version (the display copy renders it via i18n). */
|
|
15
|
+
fromVersion?: number
|
|
16
|
+
/** For an `outdated` issue: the newer catalog version available. */
|
|
17
|
+
toVersion?: number
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** A built-in's display name for an issue message (humanise its catalog id as a fallback). */
|
|
21
|
+
function builtinName(id: string, stored: MergeThresholdPreset | undefined): string {
|
|
22
|
+
if (stored) return stored.name
|
|
23
|
+
// `mp_manual_review` -> "Manual review" — only used until the row is reseeded into existence.
|
|
24
|
+
return id.replace(/^mp_/, '').replace(/_/g, ' ')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Detect built-in merge presets the workspace should reseed for the startup advisory: a stored
|
|
29
|
+
* built-in whose catalog definition moved ahead (offer to adopt it) and a brand-new built-in
|
|
30
|
+
* that appeared in the catalog but isn't in the workspace yet (offer to add it). The catalog
|
|
31
|
+
* versions the snapshot ships ARE the set of built-in ids, so detection is entirely client-side:
|
|
32
|
+
* a stored preset is a built-in iff its id is a catalog key, and a catalog key with no stored
|
|
33
|
+
* preset is a new built-in.
|
|
34
|
+
*/
|
|
35
|
+
export function useMergePresetHealth() {
|
|
36
|
+
const store = useMergePresetsStore()
|
|
37
|
+
|
|
38
|
+
const issues = computed<MergePresetIssue[]>(() => {
|
|
39
|
+
const out: MergePresetIssue[] = []
|
|
40
|
+
const byId = new Map(store.presets.map((p) => [p.id, p]))
|
|
41
|
+
for (const [id, catalogVersion] of Object.entries(store.catalogVersions)) {
|
|
42
|
+
const stored = byId.get(id)
|
|
43
|
+
if (!stored) {
|
|
44
|
+
out.push({ type: 'new', id, name: builtinName(id, undefined) })
|
|
45
|
+
continue
|
|
46
|
+
}
|
|
47
|
+
if (catalogVersion > (stored.version ?? 0)) {
|
|
48
|
+
out.push({
|
|
49
|
+
type: 'outdated',
|
|
50
|
+
id,
|
|
51
|
+
name: stored.name,
|
|
52
|
+
fromVersion: stored.version ?? 0,
|
|
53
|
+
toVersion: catalogVersion,
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return out
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
const hasIssues = computed(() => issues.value.length > 0)
|
|
61
|
+
const newPresets = computed(() => issues.value.filter((i) => i.type === 'new'))
|
|
62
|
+
const outdated = computed(() => issues.value.filter((i) => i.type === 'outdated'))
|
|
63
|
+
|
|
64
|
+
return { issues, hasIssues, newPresets, outdated }
|
|
65
|
+
}
|
package/app/pages/index.vue
CHANGED
|
@@ -62,6 +62,10 @@ const FragmentLibraryPanel = defineAsyncComponent(
|
|
|
62
62
|
const PipelineHealthModal = defineAsyncComponent(
|
|
63
63
|
() => import('~/components/pipeline/PipelineHealthModal.vue'),
|
|
64
64
|
)
|
|
65
|
+
// Startup advisory for new / outdated built-in merge presets — same once-per-session pattern.
|
|
66
|
+
const MergePresetHealthModal = defineAsyncComponent(
|
|
67
|
+
() => import('~/components/settings/MergePresetHealthModal.vue'),
|
|
68
|
+
)
|
|
65
69
|
const IntegrationsHub = defineAsyncComponent(
|
|
66
70
|
() => import('~/components/layout/IntegrationsHub.vue'),
|
|
67
71
|
)
|
|
@@ -150,6 +154,18 @@ watch(
|
|
|
150
154
|
},
|
|
151
155
|
{ immediate: true },
|
|
152
156
|
)
|
|
157
|
+
// Same advisory for built-in merge presets: surface new / outdated ones once per session. Defers
|
|
158
|
+
// to the pipeline advisory when both fire, so at most one modal auto-opens on a given load.
|
|
159
|
+
const { hasIssues: mergePresetIssues } = useMergePresetHealth()
|
|
160
|
+
watch(
|
|
161
|
+
() => [workspace.ready, mergePresetIssues.value, ui.pipelineHealthOpen],
|
|
162
|
+
() => {
|
|
163
|
+
if (workspace.ready && mergePresetIssues.value && !ui.pipelineHealthOpen) {
|
|
164
|
+
ui.maybeOpenMergePresetHealth()
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
{ immediate: true },
|
|
168
|
+
)
|
|
153
169
|
|
|
154
170
|
// Auto-open the right AI-onboarding dialog once per session: the no-source prompt takes
|
|
155
171
|
// precedence over the preset-mismatch prompt. Honour the per-session dismissed flags so a
|
|
@@ -303,6 +319,7 @@ watch(
|
|
|
303
319
|
<SlackPanel v-if="ui.slackOpen" />
|
|
304
320
|
<FragmentLibraryPanel v-if="ui.fragmentLibraryOpen" />
|
|
305
321
|
<PipelineHealthModal v-if="ui.pipelineHealthOpen" />
|
|
322
|
+
<MergePresetHealthModal v-if="ui.mergePresetHealthOpen" />
|
|
306
323
|
<IntegrationsHub v-if="ui.integrationsOpen" />
|
|
307
324
|
<PersonalSetupModal v-if="ui.personalSetupOpen" />
|
|
308
325
|
<WorkspaceSettingsPanel v-if="ui.workspaceSettingsOpen" />
|
|
@@ -13,9 +13,18 @@ export const useMergePresetsStore = defineStore('mergePresets', () => {
|
|
|
13
13
|
const api = useApi()
|
|
14
14
|
|
|
15
15
|
const presets = ref<MergeThresholdPreset[]>([])
|
|
16
|
+
/**
|
|
17
|
+
* Current built-in catalog versions (`seedMergePresets()`), keyed by preset id, from the
|
|
18
|
+
* workspace snapshot. The keys ARE the set of built-in ids: a stored preset whose id is a
|
|
19
|
+
* key here is a built-in (and is outdated when its `version` is below the catalog value),
|
|
20
|
+
* and a key with no matching stored preset is a NEW built-in the workspace can add. Drives
|
|
21
|
+
* `useMergePresetHealth`.
|
|
22
|
+
*/
|
|
23
|
+
const catalogVersions = ref<Record<string, number>>({})
|
|
16
24
|
|
|
17
|
-
function hydrate(list: MergeThresholdPreset[]) {
|
|
25
|
+
function hydrate(list: MergeThresholdPreset[], versions?: Record<string, number>) {
|
|
18
26
|
presets.value = [...list].sort((a, b) => a.createdAt - b.createdAt)
|
|
27
|
+
if (versions) catalogVersions.value = versions
|
|
19
28
|
}
|
|
20
29
|
|
|
21
30
|
/** The workspace default (fallback for a task that picks none). */
|
|
@@ -50,5 +59,27 @@ export const useMergePresetsStore = defineStore('mergePresets', () => {
|
|
|
50
59
|
await ws.refresh()
|
|
51
60
|
}
|
|
52
61
|
|
|
53
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Reseed a built-in preset from the backend's current catalog: adopt an updated definition,
|
|
64
|
+
* repair a drifted one, or materialise a NEW built-in that appeared after the workspace was
|
|
65
|
+
* created. The `presetId` is the catalog id (e.g. `mp_balanced`). Refreshes the snapshot.
|
|
66
|
+
*/
|
|
67
|
+
async function reseed(presetId: string) {
|
|
68
|
+
const ws = useWorkspaceStore()
|
|
69
|
+
const updated = await api.reseedMergePreset(ws.requireId(), presetId)
|
|
70
|
+
await ws.refresh()
|
|
71
|
+
return updated
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
presets,
|
|
76
|
+
catalogVersions,
|
|
77
|
+
defaultPreset,
|
|
78
|
+
resolve,
|
|
79
|
+
hydrate,
|
|
80
|
+
create,
|
|
81
|
+
update,
|
|
82
|
+
remove,
|
|
83
|
+
reseed,
|
|
84
|
+
}
|
|
54
85
|
})
|
package/app/stores/ui.ts
CHANGED
|
@@ -24,6 +24,11 @@ export const useUiStore = defineStore('ui', () => {
|
|
|
24
24
|
// session so it does not re-pop on every snapshot re-hydration.
|
|
25
25
|
const pipelineHealthOpen = ref(false)
|
|
26
26
|
const pipelineHealthSeen = ref(false)
|
|
27
|
+
// Merge-preset health startup advisory: lists built-ins with a newer catalog version (reseed)
|
|
28
|
+
// and new built-in presets the workspace can add. `mergePresetHealthSeen` gates auto-open to
|
|
29
|
+
// once per session so it does not re-pop on every snapshot re-hydration (mirrors pipelines).
|
|
30
|
+
const mergePresetHealthOpen = ref(false)
|
|
31
|
+
const mergePresetHealthSeen = ref(false)
|
|
27
32
|
const decisionContext = ref<{ instanceId: string; decisionId: string } | null>(null)
|
|
28
33
|
|
|
29
34
|
// Document-source integration modals, keyed by source. `documentImport` and
|
|
@@ -250,6 +255,22 @@ export const useUiStore = defineStore('ui', () => {
|
|
|
250
255
|
pipelineHealthOpen.value = false
|
|
251
256
|
}
|
|
252
257
|
|
|
258
|
+
/** Auto-open the merge-preset health advisory once per session (no-op after it's been shown). */
|
|
259
|
+
function maybeOpenMergePresetHealth() {
|
|
260
|
+
if (mergePresetHealthSeen.value) return
|
|
261
|
+
mergePresetHealthSeen.value = true
|
|
262
|
+
mergePresetHealthOpen.value = true
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function openMergePresetHealth() {
|
|
266
|
+
mergePresetHealthSeen.value = true
|
|
267
|
+
mergePresetHealthOpen.value = true
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function closeMergePresetHealth() {
|
|
271
|
+
mergePresetHealthOpen.value = false
|
|
272
|
+
}
|
|
273
|
+
|
|
253
274
|
function openDecision(instanceId: string, decisionId: string) {
|
|
254
275
|
decisionContext.value = { instanceId, decisionId }
|
|
255
276
|
}
|
|
@@ -658,6 +679,8 @@ export const useUiStore = defineStore('ui', () => {
|
|
|
658
679
|
builderOpen,
|
|
659
680
|
pipelineHealthOpen,
|
|
660
681
|
pipelineHealthSeen,
|
|
682
|
+
mergePresetHealthOpen,
|
|
683
|
+
mergePresetHealthSeen,
|
|
661
684
|
decisionContext,
|
|
662
685
|
documentConnect,
|
|
663
686
|
documentImport,
|
|
@@ -715,6 +738,9 @@ export const useUiStore = defineStore('ui', () => {
|
|
|
715
738
|
maybeOpenPipelineHealth,
|
|
716
739
|
openPipelineHealth,
|
|
717
740
|
closePipelineHealth,
|
|
741
|
+
maybeOpenMergePresetHealth,
|
|
742
|
+
openMergePresetHealth,
|
|
743
|
+
closeMergePresetHealth,
|
|
718
744
|
openDecision,
|
|
719
745
|
closeDecision,
|
|
720
746
|
openApprovalDetail,
|
package/app/stores/workspace.ts
CHANGED
|
@@ -88,7 +88,10 @@ export const useWorkspaceStore = defineStore(
|
|
|
88
88
|
useAgentRunsStore().hydrate(snapshot.bootstrapJobs ?? [])
|
|
89
89
|
useAgentRunsStore().hydrateEnvConfigRepair(snapshot.envConfigRepairJobs ?? [])
|
|
90
90
|
useNotificationsStore().hydrate(snapshot.notifications ?? [])
|
|
91
|
-
useMergePresetsStore().hydrate(
|
|
91
|
+
useMergePresetsStore().hydrate(
|
|
92
|
+
snapshot.mergePresets ?? [],
|
|
93
|
+
snapshot.mergePresetCatalogVersions,
|
|
94
|
+
)
|
|
92
95
|
useWorkspaceSettingsStore().hydrate(snapshot.settings)
|
|
93
96
|
useAgentConfigStore().hydrate(snapshot.agentConfigCatalog ?? [])
|
|
94
97
|
useModelPresetsStore().hydrate(snapshot.modelPresets ?? [])
|
package/app/utils/mergePreset.ts
CHANGED
|
@@ -7,6 +7,8 @@ import type { MergeThresholdPreset } from '~/types/merge'
|
|
|
7
7
|
* rendered as whole percents.
|
|
8
8
|
*/
|
|
9
9
|
export function mergePresetThresholds(p: MergeThresholdPreset): string {
|
|
10
|
+
// Auto-merge disabled: the thresholds don't apply, every PR goes to human review.
|
|
11
|
+
if (!p.autoMergeEnabled) return `manual review only · ${p.ciMaxAttempts} CI fixes`
|
|
10
12
|
const pct = (n: number) => `${Math.round(n * 100)}%`
|
|
11
13
|
return `cx ≤${pct(p.maxComplexity)} · risk ≤${pct(p.maxRisk)} · impact ≤${pct(
|
|
12
14
|
p.maxImpact,
|
package/i18n/locales/en.json
CHANGED
|
@@ -1643,8 +1643,11 @@
|
|
|
1643
1643
|
"maxImpact": "Max impact %",
|
|
1644
1644
|
"ciMaxAttempts": "CI-fix attempts",
|
|
1645
1645
|
"maxRequirementIterations": "Requirement iterations",
|
|
1646
|
-
"maxRequirementConcernAllowed": "Auto-pass concerns at or below"
|
|
1646
|
+
"maxRequirementConcernAllowed": "Auto-pass concerns at or below",
|
|
1647
|
+
"autoMerge": "Auto-merge"
|
|
1647
1648
|
},
|
|
1649
|
+
"autoMergeOnHint": "Merge automatically when within thresholds.",
|
|
1650
|
+
"autoMergeOffHint": "Always route the PR to a human review.",
|
|
1648
1651
|
"newPreset": "New preset",
|
|
1649
1652
|
"create": {
|
|
1650
1653
|
"name": "Name",
|
|
@@ -2529,6 +2532,25 @@
|
|
|
2529
2532
|
}
|
|
2530
2533
|
}
|
|
2531
2534
|
},
|
|
2535
|
+
"mergePreset": {
|
|
2536
|
+
"health": {
|
|
2537
|
+
"title": "Merge preset updates",
|
|
2538
|
+
"allValid": "All built-in merge presets are up to date.",
|
|
2539
|
+
"newHeading": "New presets available",
|
|
2540
|
+
"newDescription": "New built-in merge presets have shipped. Add them to this board's library.",
|
|
2541
|
+
"add": "Add",
|
|
2542
|
+
"updatesHeading": "Updates available",
|
|
2543
|
+
"updatesDescription": "A newer version of these built-in merge presets has shipped. Reseed to adopt it (the default and ordering are kept).",
|
|
2544
|
+
"versionAvailable": "Version {from} → {to} available.",
|
|
2545
|
+
"reseed": "Reseed",
|
|
2546
|
+
"reseedAll": "Update all ({count})",
|
|
2547
|
+
"dismiss": "Dismiss",
|
|
2548
|
+
"done": "Done",
|
|
2549
|
+
"toast": {
|
|
2550
|
+
"reseedFailed": "Could not reseed merge preset"
|
|
2551
|
+
}
|
|
2552
|
+
}
|
|
2553
|
+
},
|
|
2532
2554
|
"palette": {
|
|
2533
2555
|
"hint": "Click an agent to append it to the pipeline.",
|
|
2534
2556
|
"customAgents": "Custom agents"
|
package/i18n/locales/es.json
CHANGED
|
@@ -1499,7 +1499,8 @@
|
|
|
1499
1499
|
"maxImpact": "Impacto máx. %",
|
|
1500
1500
|
"ciMaxAttempts": "Intentos de corrección de CI",
|
|
1501
1501
|
"maxRequirementIterations": "Iteraciones de requisitos",
|
|
1502
|
-
"maxRequirementConcernAllowed": "Aprobación automática de inquietudes hasta"
|
|
1502
|
+
"maxRequirementConcernAllowed": "Aprobación automática de inquietudes hasta",
|
|
1503
|
+
"autoMerge": "Fusión automática"
|
|
1503
1504
|
},
|
|
1504
1505
|
"newPreset": "Nuevo ajuste",
|
|
1505
1506
|
"create": {
|
|
@@ -1520,7 +1521,9 @@
|
|
|
1520
1521
|
"createFailed": "No se pudo crear el ajuste",
|
|
1521
1522
|
"defaultFailed": "No se pudo establecer el predeterminado",
|
|
1522
1523
|
"deleteFailed": "No se pudo eliminar el ajuste"
|
|
1523
|
-
}
|
|
1524
|
+
},
|
|
1525
|
+
"autoMergeOnHint": "Fusionar automáticamente cuando esté dentro de los umbrales.",
|
|
1526
|
+
"autoMergeOffHint": "Enviar siempre el PR a revisión humana."
|
|
1524
1527
|
},
|
|
1525
1528
|
"observabilityConnection": {
|
|
1526
1529
|
"title": "Salud posterior al lanzamiento",
|
|
@@ -3498,5 +3501,24 @@
|
|
|
3498
3501
|
"saveArchFailed": "No se pudo guardar la arquitectura de referencia",
|
|
3499
3502
|
"deleteFailed": "No se pudo eliminar"
|
|
3500
3503
|
}
|
|
3504
|
+
},
|
|
3505
|
+
"mergePreset": {
|
|
3506
|
+
"health": {
|
|
3507
|
+
"title": "Actualizaciones de presets de fusión",
|
|
3508
|
+
"allValid": "Todos los presets de fusión integrados están actualizados.",
|
|
3509
|
+
"newHeading": "Nuevos presets disponibles",
|
|
3510
|
+
"newDescription": "Hay nuevos presets de fusión integrados. Añádelos a la biblioteca de este tablero.",
|
|
3511
|
+
"add": "Añadir",
|
|
3512
|
+
"updatesHeading": "Actualizaciones disponibles",
|
|
3513
|
+
"updatesDescription": "Hay una versión más reciente de estos presets de fusión integrados. Regenera para adoptarla (se conservan el predeterminado y el orden).",
|
|
3514
|
+
"versionAvailable": "Versión {from} → {to} disponible.",
|
|
3515
|
+
"reseed": "Regenerar",
|
|
3516
|
+
"reseedAll": "Actualizar todos ({count})",
|
|
3517
|
+
"dismiss": "Descartar",
|
|
3518
|
+
"done": "Hecho",
|
|
3519
|
+
"toast": {
|
|
3520
|
+
"reseedFailed": "No se pudo regenerar el preset de fusión"
|
|
3521
|
+
}
|
|
3522
|
+
}
|
|
3501
3523
|
}
|
|
3502
3524
|
}
|
package/i18n/locales/fr.json
CHANGED
|
@@ -1499,7 +1499,8 @@
|
|
|
1499
1499
|
"maxImpact": "Impact max %",
|
|
1500
1500
|
"ciMaxAttempts": "Tentatives de correction CI",
|
|
1501
1501
|
"maxRequirementIterations": "Itérations d'exigences",
|
|
1502
|
-
"maxRequirementConcernAllowed": "Validation auto. des préoccupations jusqu'à"
|
|
1502
|
+
"maxRequirementConcernAllowed": "Validation auto. des préoccupations jusqu'à",
|
|
1503
|
+
"autoMerge": "Fusion automatique"
|
|
1503
1504
|
},
|
|
1504
1505
|
"newPreset": "Nouveau préréglage",
|
|
1505
1506
|
"create": {
|
|
@@ -1520,7 +1521,9 @@
|
|
|
1520
1521
|
"createFailed": "Impossible de créer le préréglage",
|
|
1521
1522
|
"defaultFailed": "Impossible de définir par défaut",
|
|
1522
1523
|
"deleteFailed": "Impossible de supprimer le préréglage"
|
|
1523
|
-
}
|
|
1524
|
+
},
|
|
1525
|
+
"autoMergeOnHint": "Fusionner automatiquement si dans les seuils.",
|
|
1526
|
+
"autoMergeOffHint": "Toujours envoyer la PR en revue humaine."
|
|
1524
1527
|
},
|
|
1525
1528
|
"observabilityConnection": {
|
|
1526
1529
|
"title": "Santé post-publication",
|
|
@@ -3498,5 +3501,24 @@
|
|
|
3498
3501
|
"saveArchFailed": "Impossible d'enregistrer l'architecture de référence",
|
|
3499
3502
|
"deleteFailed": "Impossible de supprimer"
|
|
3500
3503
|
}
|
|
3504
|
+
},
|
|
3505
|
+
"mergePreset": {
|
|
3506
|
+
"health": {
|
|
3507
|
+
"title": "Mises à jour des presets de fusion",
|
|
3508
|
+
"allValid": "Tous les presets de fusion intégrés sont à jour.",
|
|
3509
|
+
"newHeading": "Nouveaux presets disponibles",
|
|
3510
|
+
"newDescription": "De nouveaux presets de fusion intégrés sont arrivés. Ajoutez-les à la bibliothèque de ce tableau.",
|
|
3511
|
+
"add": "Ajouter",
|
|
3512
|
+
"updatesHeading": "Mises à jour disponibles",
|
|
3513
|
+
"updatesDescription": "Une version plus récente de ces presets de fusion intégrés est arrivée. Régénérez pour l'adopter (le preset par défaut et l'ordre sont conservés).",
|
|
3514
|
+
"versionAvailable": "Version {from} → {to} disponible.",
|
|
3515
|
+
"reseed": "Régénérer",
|
|
3516
|
+
"reseedAll": "Tout mettre à jour ({count})",
|
|
3517
|
+
"dismiss": "Ignorer",
|
|
3518
|
+
"done": "Terminé",
|
|
3519
|
+
"toast": {
|
|
3520
|
+
"reseedFailed": "Impossible de régénérer le preset de fusion"
|
|
3521
|
+
}
|
|
3522
|
+
}
|
|
3501
3523
|
}
|
|
3502
3524
|
}
|
package/i18n/locales/he.json
CHANGED
|
@@ -1598,7 +1598,8 @@
|
|
|
1598
1598
|
"maxImpact": "השפעה מרבית %",
|
|
1599
1599
|
"ciMaxAttempts": "ניסיונות תיקון CI",
|
|
1600
1600
|
"maxRequirementIterations": "איטרציות דרישות",
|
|
1601
|
-
"maxRequirementConcernAllowed": "מעבר אוטומטי בחששות ברף או מתחתיו"
|
|
1601
|
+
"maxRequirementConcernAllowed": "מעבר אוטומטי בחששות ברף או מתחתיו",
|
|
1602
|
+
"autoMerge": "מיזוג אוטומטי"
|
|
1602
1603
|
},
|
|
1603
1604
|
"newPreset": "תצורה חדשה",
|
|
1604
1605
|
"create": {
|
|
@@ -1619,7 +1620,9 @@
|
|
|
1619
1620
|
"createFailed": "לא ניתן היה ליצור תצורה",
|
|
1620
1621
|
"defaultFailed": "לא ניתן היה להגדיר ברירת מחדל",
|
|
1621
1622
|
"deleteFailed": "לא ניתן היה למחוק את התצורה"
|
|
1622
|
-
}
|
|
1623
|
+
},
|
|
1624
|
+
"autoMergeOnHint": "מזג אוטומטית כשבתוך הספים.",
|
|
1625
|
+
"autoMergeOffHint": "נתב תמיד את ה-PR לבדיקה אנושית."
|
|
1623
1626
|
},
|
|
1624
1627
|
"observabilityConnection": {
|
|
1625
1628
|
"title": "בריאות שלאחר שחרור",
|
|
@@ -3509,5 +3512,24 @@
|
|
|
3509
3512
|
"saveArchFailed": "לא ניתן היה לשמור ארכיטקטורת ייחוס",
|
|
3510
3513
|
"deleteFailed": "לא ניתן היה למחוק"
|
|
3511
3514
|
}
|
|
3515
|
+
},
|
|
3516
|
+
"mergePreset": {
|
|
3517
|
+
"health": {
|
|
3518
|
+
"title": "עדכוני קביעות מיזוג",
|
|
3519
|
+
"allValid": "כל קביעות המיזוג המובנות מעודכנות.",
|
|
3520
|
+
"newHeading": "קביעות חדשות זמינות",
|
|
3521
|
+
"newDescription": "הגיעו קביעות מיזוג מובנות חדשות. הוסף אותן לספריית הלוח הזה.",
|
|
3522
|
+
"add": "הוסף",
|
|
3523
|
+
"updatesHeading": "עדכונים זמינים",
|
|
3524
|
+
"updatesDescription": "גרסה חדשה יותר של קביעות המיזוג המובנות האלה הגיעה. זרע מחדש כדי לאמץ אותה (ברירת המחדל והסדר נשמרים).",
|
|
3525
|
+
"versionAvailable": "גרסה {from} → {to} זמינה.",
|
|
3526
|
+
"reseed": "זרע מחדש",
|
|
3527
|
+
"reseedAll": "עדכן הכל ({count})",
|
|
3528
|
+
"dismiss": "התעלם",
|
|
3529
|
+
"done": "בוצע",
|
|
3530
|
+
"toast": {
|
|
3531
|
+
"reseedFailed": "לא ניתן לזרוע מחדש את קביעת המיזוג"
|
|
3532
|
+
}
|
|
3533
|
+
}
|
|
3512
3534
|
}
|
|
3513
3535
|
}
|
package/i18n/locales/ja.json
CHANGED
|
@@ -1600,7 +1600,8 @@
|
|
|
1600
1600
|
"maxImpact": "最大影響度 %",
|
|
1601
1601
|
"ciMaxAttempts": "CI 修正の試行回数",
|
|
1602
1602
|
"maxRequirementIterations": "要件のイテレーション回数",
|
|
1603
|
-
"maxRequirementConcernAllowed": "この水準以下の懸念を自動承認"
|
|
1603
|
+
"maxRequirementConcernAllowed": "この水準以下の懸念を自動承認",
|
|
1604
|
+
"autoMerge": "自動マージ"
|
|
1604
1605
|
},
|
|
1605
1606
|
"newPreset": "新しいプリセット",
|
|
1606
1607
|
"create": {
|
|
@@ -1621,7 +1622,9 @@
|
|
|
1621
1622
|
"createFailed": "プリセットを作成できませんでした",
|
|
1622
1623
|
"defaultFailed": "デフォルトを設定できませんでした",
|
|
1623
1624
|
"deleteFailed": "プリセットを削除できませんでした"
|
|
1624
|
-
}
|
|
1625
|
+
},
|
|
1626
|
+
"autoMergeOnHint": "しきい値内なら自動的にマージします。",
|
|
1627
|
+
"autoMergeOffHint": "常にPRを人間のレビューに回します。"
|
|
1625
1628
|
},
|
|
1626
1629
|
"observabilityConnection": {
|
|
1627
1630
|
"title": "リリース後のヘルス",
|
|
@@ -3511,5 +3514,24 @@
|
|
|
3511
3514
|
"saveArchFailed": "リファレンスアーキテクチャを保存できませんでした",
|
|
3512
3515
|
"deleteFailed": "削除できませんでした"
|
|
3513
3516
|
}
|
|
3517
|
+
},
|
|
3518
|
+
"mergePreset": {
|
|
3519
|
+
"health": {
|
|
3520
|
+
"title": "マージプリセットの更新",
|
|
3521
|
+
"allValid": "組み込みのマージプリセットはすべて最新です。",
|
|
3522
|
+
"newHeading": "新しいプリセットがあります",
|
|
3523
|
+
"newDescription": "新しい組み込みマージプリセットが追加されました。このボードのライブラリに追加してください。",
|
|
3524
|
+
"add": "追加",
|
|
3525
|
+
"updatesHeading": "更新あり",
|
|
3526
|
+
"updatesDescription": "これらの組み込みマージプリセットの新しいバージョンがあります。再シードして取り込みます(既定と並び順は保持されます)。",
|
|
3527
|
+
"versionAvailable": "バージョン {from} → {to} が利用可能です。",
|
|
3528
|
+
"reseed": "再シード",
|
|
3529
|
+
"reseedAll": "すべて更新 ({count})",
|
|
3530
|
+
"dismiss": "閉じる",
|
|
3531
|
+
"done": "完了",
|
|
3532
|
+
"toast": {
|
|
3533
|
+
"reseedFailed": "マージプリセットを再シードできませんでした"
|
|
3534
|
+
}
|
|
3535
|
+
}
|
|
3514
3536
|
}
|
|
3515
3537
|
}
|
package/i18n/locales/pl.json
CHANGED
|
@@ -1499,7 +1499,8 @@
|
|
|
1499
1499
|
"maxImpact": "Maks. wpływ %",
|
|
1500
1500
|
"ciMaxAttempts": "Próby naprawy CI",
|
|
1501
1501
|
"maxRequirementIterations": "Iteracje wymagań",
|
|
1502
|
-
"maxRequirementConcernAllowed": "Automatyczne zaliczenie zastrzeżeń do"
|
|
1502
|
+
"maxRequirementConcernAllowed": "Automatyczne zaliczenie zastrzeżeń do",
|
|
1503
|
+
"autoMerge": "Auto-scalanie"
|
|
1503
1504
|
},
|
|
1504
1505
|
"newPreset": "Nowe ustawienie",
|
|
1505
1506
|
"create": {
|
|
@@ -1520,7 +1521,9 @@
|
|
|
1520
1521
|
"createFailed": "Nie można utworzyć ustawienia",
|
|
1521
1522
|
"defaultFailed": "Nie można ustawić jako domyślne",
|
|
1522
1523
|
"deleteFailed": "Nie można usunąć ustawienia"
|
|
1523
|
-
}
|
|
1524
|
+
},
|
|
1525
|
+
"autoMergeOnHint": "Scalaj automatycznie, gdy mieści się w progach.",
|
|
1526
|
+
"autoMergeOffHint": "Zawsze kieruj PR do recenzji człowieka."
|
|
1524
1527
|
},
|
|
1525
1528
|
"observabilityConnection": {
|
|
1526
1529
|
"title": "Kondycja po wydaniu",
|
|
@@ -3498,5 +3501,24 @@
|
|
|
3498
3501
|
"saveArchFailed": "Nie udało się zapisać architektury referencyjnej",
|
|
3499
3502
|
"deleteFailed": "Nie udało się usunąć"
|
|
3500
3503
|
}
|
|
3504
|
+
},
|
|
3505
|
+
"mergePreset": {
|
|
3506
|
+
"health": {
|
|
3507
|
+
"title": "Aktualizacje presetów scalania",
|
|
3508
|
+
"allValid": "Wszystkie wbudowane presety scalania są aktualne.",
|
|
3509
|
+
"newHeading": "Dostępne nowe presety",
|
|
3510
|
+
"newDescription": "Pojawiły się nowe wbudowane presety scalania. Dodaj je do biblioteki tej tablicy.",
|
|
3511
|
+
"add": "Dodaj",
|
|
3512
|
+
"updatesHeading": "Dostępne aktualizacje",
|
|
3513
|
+
"updatesDescription": "Dostępna jest nowsza wersja tych wbudowanych presetów scalania. Zregeneruj, aby ją przyjąć (domyślny i kolejność są zachowane).",
|
|
3514
|
+
"versionAvailable": "Dostępna wersja {from} → {to}.",
|
|
3515
|
+
"reseed": "Zregeneruj",
|
|
3516
|
+
"reseedAll": "Zaktualizuj wszystkie ({count})",
|
|
3517
|
+
"dismiss": "Odrzuć",
|
|
3518
|
+
"done": "Gotowe",
|
|
3519
|
+
"toast": {
|
|
3520
|
+
"reseedFailed": "Nie udało się zregenerować presetu scalania"
|
|
3521
|
+
}
|
|
3522
|
+
}
|
|
3501
3523
|
}
|
|
3502
3524
|
}
|
package/i18n/locales/tr.json
CHANGED
|
@@ -1600,7 +1600,8 @@
|
|
|
1600
1600
|
"maxImpact": "Maks. etki %",
|
|
1601
1601
|
"ciMaxAttempts": "CI düzeltme denemeleri",
|
|
1602
1602
|
"maxRequirementIterations": "Gereksinim yinelemeleri",
|
|
1603
|
-
"maxRequirementConcernAllowed": "Şu düzeyde veya altında otomatik geç"
|
|
1603
|
+
"maxRequirementConcernAllowed": "Şu düzeyde veya altında otomatik geç",
|
|
1604
|
+
"autoMerge": "Otomatik birleştirme"
|
|
1604
1605
|
},
|
|
1605
1606
|
"newPreset": "Yeni ön ayar",
|
|
1606
1607
|
"create": {
|
|
@@ -1621,7 +1622,9 @@
|
|
|
1621
1622
|
"createFailed": "Ön ayar oluşturulamadı",
|
|
1622
1623
|
"defaultFailed": "Varsayılan ayarlanamadı",
|
|
1623
1624
|
"deleteFailed": "Ön ayar silinemedi"
|
|
1624
|
-
}
|
|
1625
|
+
},
|
|
1626
|
+
"autoMergeOnHint": "Eşiklerin içindeyken otomatik birleştir.",
|
|
1627
|
+
"autoMergeOffHint": "PR'yi her zaman insan incelemesine gönder."
|
|
1625
1628
|
},
|
|
1626
1629
|
"observabilityConnection": {
|
|
1627
1630
|
"title": "Sürüm sonrası sağlık",
|
|
@@ -3511,5 +3514,24 @@
|
|
|
3511
3514
|
"saveArchFailed": "Referans mimari kaydedilemedi",
|
|
3512
3515
|
"deleteFailed": "Silinemedi"
|
|
3513
3516
|
}
|
|
3517
|
+
},
|
|
3518
|
+
"mergePreset": {
|
|
3519
|
+
"health": {
|
|
3520
|
+
"title": "Birleştirme ön ayarı güncellemeleri",
|
|
3521
|
+
"allValid": "Tüm yerleşik birleştirme ön ayarları güncel.",
|
|
3522
|
+
"newHeading": "Yeni ön ayarlar mevcut",
|
|
3523
|
+
"newDescription": "Yeni yerleşik birleştirme ön ayarları geldi. Bu panonun kütüphanesine ekleyin.",
|
|
3524
|
+
"add": "Ekle",
|
|
3525
|
+
"updatesHeading": "Güncellemeler mevcut",
|
|
3526
|
+
"updatesDescription": "Bu yerleşik birleştirme ön ayarlarının daha yeni bir sürümü geldi. Benimsemek için yeniden tohumlayın (varsayılan ve sıralama korunur).",
|
|
3527
|
+
"versionAvailable": "Sürüm {from} → {to} mevcut.",
|
|
3528
|
+
"reseed": "Yeniden tohumla",
|
|
3529
|
+
"reseedAll": "Tümünü güncelle ({count})",
|
|
3530
|
+
"dismiss": "Yoksay",
|
|
3531
|
+
"done": "Tamam",
|
|
3532
|
+
"toast": {
|
|
3533
|
+
"reseedFailed": "Birleştirme ön ayarı yeniden tohumlanamadı"
|
|
3534
|
+
}
|
|
3535
|
+
}
|
|
3514
3536
|
}
|
|
3515
3537
|
}
|
package/i18n/locales/uk.json
CHANGED
|
@@ -1499,7 +1499,8 @@
|
|
|
1499
1499
|
"maxImpact": "Макс. вплив %",
|
|
1500
1500
|
"ciMaxAttempts": "Спроби виправлення CI",
|
|
1501
1501
|
"maxRequirementIterations": "Ітерації вимог",
|
|
1502
|
-
"maxRequirementConcernAllowed": "Авто-пропуск зауважень до"
|
|
1502
|
+
"maxRequirementConcernAllowed": "Авто-пропуск зауважень до",
|
|
1503
|
+
"autoMerge": "Автозлиття"
|
|
1503
1504
|
},
|
|
1504
1505
|
"newPreset": "Новий набір",
|
|
1505
1506
|
"create": {
|
|
@@ -1520,7 +1521,9 @@
|
|
|
1520
1521
|
"createFailed": "Не вдалося створити набір",
|
|
1521
1522
|
"defaultFailed": "Не вдалося встановити за замовчуванням",
|
|
1522
1523
|
"deleteFailed": "Не вдалося видалити набір"
|
|
1523
|
-
}
|
|
1524
|
+
},
|
|
1525
|
+
"autoMergeOnHint": "Зливати автоматично, коли в межах порогів.",
|
|
1526
|
+
"autoMergeOffHint": "Завжди надсилати PR на перевірку людиною."
|
|
1524
1527
|
},
|
|
1525
1528
|
"observabilityConnection": {
|
|
1526
1529
|
"title": "Стан після випуску",
|
|
@@ -3498,5 +3501,24 @@
|
|
|
3498
3501
|
"saveArchFailed": "Не вдалося зберегти еталонну архітектуру",
|
|
3499
3502
|
"deleteFailed": "Не вдалося видалити"
|
|
3500
3503
|
}
|
|
3504
|
+
},
|
|
3505
|
+
"mergePreset": {
|
|
3506
|
+
"health": {
|
|
3507
|
+
"title": "Оновлення пресетів злиття",
|
|
3508
|
+
"allValid": "Усі вбудовані пресети злиття актуальні.",
|
|
3509
|
+
"newHeading": "Доступні нові пресети",
|
|
3510
|
+
"newDescription": "З'явилися нові вбудовані пресети злиття. Додайте їх до бібліотеки цієї дошки.",
|
|
3511
|
+
"add": "Додати",
|
|
3512
|
+
"updatesHeading": "Доступні оновлення",
|
|
3513
|
+
"updatesDescription": "Доступна новіша версія цих вбудованих пресетів злиття. Перегенеруйте, щоб застосувати її (стандартний пресет і порядок збережено).",
|
|
3514
|
+
"versionAvailable": "Доступна версія {from} → {to}.",
|
|
3515
|
+
"reseed": "Перегенерувати",
|
|
3516
|
+
"reseedAll": "Оновити всі ({count})",
|
|
3517
|
+
"dismiss": "Відхилити",
|
|
3518
|
+
"done": "Готово",
|
|
3519
|
+
"toast": {
|
|
3520
|
+
"reseedFailed": "Не вдалося перегенерувати пресет злиття"
|
|
3521
|
+
}
|
|
3522
|
+
}
|
|
3501
3523
|
}
|
|
3502
3524
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.62.0",
|
|
4
4
|
"description": "Reusable Nuxt layer for the Agent Architecture Board SPA (components, stores, composables, pages). Consume it from a thin deployment app via `extends: ['@cat-factory/app']` and point it at your backend with NUXT_PUBLIC_API_BASE. See deploy/frontend for an example.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"valibot": "^1.4.2",
|
|
35
35
|
"vue": "^3.5.39",
|
|
36
36
|
"wretch": "^3.0.9",
|
|
37
|
-
"@cat-factory/contracts": "0.
|
|
37
|
+
"@cat-factory/contracts": "0.69.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@toad-contracts/testing": "0.3.2",
|