@cat-factory/app 0.107.7 → 0.108.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/settings/ModelPresetHealthModal.vue +180 -0
- package/app/composables/api/presets.ts +6 -0
- package/app/composables/useModelPresetHealth.ts +65 -0
- package/app/pages/index.vue +23 -0
- package/app/stores/modelPresets.ts +49 -2
- package/app/stores/ui.ts +26 -0
- package/app/stores/workspace.ts +4 -1
- package/i18n/locales/de.json +19 -0
- package/i18n/locales/en.json +19 -0
- package/i18n/locales/es.json +19 -0
- package/i18n/locales/fr.json +19 -0
- package/i18n/locales/he.json +19 -0
- package/i18n/locales/it.json +19 -0
- package/i18n/locales/ja.json +19 -0
- package/i18n/locales/pl.json +19 -0
- package/i18n/locales/tr.json +19 -0
- package/i18n/locales/uk.json +19 -0
- package/package.json +2 -2
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// Startup advisory for built-in model presets that drifted from the catalog. Opened once per
|
|
3
|
+
// session from the board page when `useModelPresetHealth` 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 useModelPresetHealth); the actions hit the modelPresets store.
|
|
8
|
+
const { t } = useI18n()
|
|
9
|
+
const ui = useUiStore()
|
|
10
|
+
const presets = useModelPresetsStore()
|
|
11
|
+
const { newPresets, outdated, hasIssues } = useModelPresetHealth()
|
|
12
|
+
const toast = useToast()
|
|
13
|
+
|
|
14
|
+
const open = computed({
|
|
15
|
+
get: () => ui.modelPresetHealthOpen,
|
|
16
|
+
set: (v: boolean) => {
|
|
17
|
+
if (!v) ui.closeModelPresetHealth()
|
|
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('modelPreset.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, refreshing the board once. */
|
|
45
|
+
async function reseedAll() {
|
|
46
|
+
const ids = [...new Set([...newPresets.value, ...outdated.value].map((i) => i.id))]
|
|
47
|
+
busy.value = new Set([...busy.value, ...ids])
|
|
48
|
+
try {
|
|
49
|
+
await presets.reseedMany(ids)
|
|
50
|
+
} catch (e) {
|
|
51
|
+
toast.add({
|
|
52
|
+
title: t('modelPreset.health.toast.reseedFailed'),
|
|
53
|
+
description: e instanceof Error ? e.message : String(e),
|
|
54
|
+
icon: 'i-lucide-triangle-alert',
|
|
55
|
+
color: 'error',
|
|
56
|
+
})
|
|
57
|
+
} finally {
|
|
58
|
+
const next = new Set(busy.value)
|
|
59
|
+
for (const id of ids) next.delete(id)
|
|
60
|
+
busy.value = next
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const reseedableCount = computed(
|
|
65
|
+
() => new Set([...newPresets.value, ...outdated.value].map((i) => i.id)).size,
|
|
66
|
+
)
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<template>
|
|
70
|
+
<UModal v-model:open="open" :title="t('modelPreset.health.title')" :ui="{ content: 'max-w-2xl' }">
|
|
71
|
+
<template #body>
|
|
72
|
+
<div v-if="!hasIssues" class="py-6 text-center text-sm text-slate-400">
|
|
73
|
+
<UIcon name="i-lucide-check-circle-2" class="mx-auto mb-2 h-8 w-8 text-emerald-400" />
|
|
74
|
+
{{ t('modelPreset.health.allValid') }}
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<div v-else class="space-y-5">
|
|
78
|
+
<!-- New built-in presets the workspace can add. -->
|
|
79
|
+
<section v-if="newPresets.length" class="space-y-2">
|
|
80
|
+
<div class="flex items-center gap-2">
|
|
81
|
+
<UIcon name="i-lucide-sparkles" class="h-4 w-4 text-emerald-400" />
|
|
82
|
+
<h3 class="text-sm font-semibold text-slate-200">
|
|
83
|
+
{{ t('modelPreset.health.newHeading') }}
|
|
84
|
+
</h3>
|
|
85
|
+
</div>
|
|
86
|
+
<p class="text-[11px] text-slate-500">{{ t('modelPreset.health.newDescription') }}</p>
|
|
87
|
+
<ul class="space-y-2">
|
|
88
|
+
<li
|
|
89
|
+
v-for="i in newPresets"
|
|
90
|
+
:key="i.id"
|
|
91
|
+
class="flex items-center justify-between gap-3 rounded-lg border border-slate-800 bg-slate-900/40 p-3"
|
|
92
|
+
>
|
|
93
|
+
<div class="min-w-0">
|
|
94
|
+
<span class="truncate text-sm font-medium text-slate-100 capitalize">{{
|
|
95
|
+
i.name
|
|
96
|
+
}}</span>
|
|
97
|
+
</div>
|
|
98
|
+
<UButton
|
|
99
|
+
size="xs"
|
|
100
|
+
color="primary"
|
|
101
|
+
variant="subtle"
|
|
102
|
+
icon="i-lucide-plus"
|
|
103
|
+
:loading="isBusy(i.id)"
|
|
104
|
+
:disabled="anyBusy"
|
|
105
|
+
@click="reseed(i.id)"
|
|
106
|
+
>
|
|
107
|
+
{{ t('modelPreset.health.add') }}
|
|
108
|
+
</UButton>
|
|
109
|
+
</li>
|
|
110
|
+
</ul>
|
|
111
|
+
</section>
|
|
112
|
+
|
|
113
|
+
<!-- Outdated built-ins: a newer catalog version is available. -->
|
|
114
|
+
<section v-if="outdated.length" class="space-y-2">
|
|
115
|
+
<div class="flex items-center gap-2">
|
|
116
|
+
<UIcon name="i-lucide-arrow-up-circle" class="h-4 w-4 text-amber-400" />
|
|
117
|
+
<h3 class="text-sm font-semibold text-slate-200">
|
|
118
|
+
{{ t('modelPreset.health.updatesHeading') }}
|
|
119
|
+
</h3>
|
|
120
|
+
</div>
|
|
121
|
+
<p class="text-[11px] text-slate-500">{{ t('modelPreset.health.updatesDescription') }}</p>
|
|
122
|
+
<ul class="space-y-2">
|
|
123
|
+
<li
|
|
124
|
+
v-for="i in outdated"
|
|
125
|
+
:key="i.id"
|
|
126
|
+
class="flex items-center justify-between gap-3 rounded-lg border border-slate-800 bg-slate-900/40 p-3"
|
|
127
|
+
>
|
|
128
|
+
<div class="min-w-0">
|
|
129
|
+
<span class="truncate text-sm font-medium text-slate-100">{{ i.name }}</span>
|
|
130
|
+
<p class="text-[11px] text-amber-400/80">
|
|
131
|
+
{{
|
|
132
|
+
t('modelPreset.health.versionAvailable', {
|
|
133
|
+
from: i.fromVersion ?? 0,
|
|
134
|
+
to: i.toVersion ?? 0,
|
|
135
|
+
})
|
|
136
|
+
}}
|
|
137
|
+
</p>
|
|
138
|
+
</div>
|
|
139
|
+
<UButton
|
|
140
|
+
size="xs"
|
|
141
|
+
color="primary"
|
|
142
|
+
variant="subtle"
|
|
143
|
+
icon="i-lucide-rotate-ccw"
|
|
144
|
+
:loading="isBusy(i.id)"
|
|
145
|
+
:disabled="anyBusy"
|
|
146
|
+
@click="reseed(i.id)"
|
|
147
|
+
>
|
|
148
|
+
{{ t('modelPreset.health.reseed') }}
|
|
149
|
+
</UButton>
|
|
150
|
+
</li>
|
|
151
|
+
</ul>
|
|
152
|
+
</section>
|
|
153
|
+
</div>
|
|
154
|
+
</template>
|
|
155
|
+
|
|
156
|
+
<template #footer>
|
|
157
|
+
<div class="flex w-full items-center justify-between gap-2">
|
|
158
|
+
<UButton
|
|
159
|
+
v-if="reseedableCount > 1"
|
|
160
|
+
color="primary"
|
|
161
|
+
variant="ghost"
|
|
162
|
+
icon="i-lucide-rotate-ccw"
|
|
163
|
+
:loading="anyBusy"
|
|
164
|
+
@click="reseedAll"
|
|
165
|
+
>
|
|
166
|
+
{{ t('modelPreset.health.reseedAll', { count: reseedableCount }) }}
|
|
167
|
+
</UButton>
|
|
168
|
+
<span v-else />
|
|
169
|
+
<UButton
|
|
170
|
+
color="neutral"
|
|
171
|
+
variant="ghost"
|
|
172
|
+
:disabled="anyBusy"
|
|
173
|
+
@click="ui.closeModelPresetHealth()"
|
|
174
|
+
>
|
|
175
|
+
{{ hasIssues ? t('modelPreset.health.dismiss') : t('modelPreset.health.done') }}
|
|
176
|
+
</UButton>
|
|
177
|
+
</div>
|
|
178
|
+
</template>
|
|
179
|
+
</UModal>
|
|
180
|
+
</template>
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
listMergePresetsContract,
|
|
7
7
|
listModelPresetsContract,
|
|
8
8
|
reseedMergePresetContract,
|
|
9
|
+
reseedModelPresetContract,
|
|
9
10
|
updateMergePresetContract,
|
|
10
11
|
updateModelPresetContract,
|
|
11
12
|
} from '@cat-factory/contracts'
|
|
@@ -60,5 +61,10 @@ export function presetsApi({ send, ws }: ApiContext) {
|
|
|
60
61
|
|
|
61
62
|
deleteModelPreset: (workspaceId: string, presetId: string) =>
|
|
62
63
|
send(deleteModelPresetContract, { pathPrefix: ws(workspaceId), pathParams: { presetId } }),
|
|
64
|
+
|
|
65
|
+
// Restore a built-in model preset to its current catalog definition (adopt an update, repair
|
|
66
|
+
// a drifted one, or materialise a new built-in that appeared). Custom presets reject this.
|
|
67
|
+
reseedModelPreset: (workspaceId: string, presetId: string) =>
|
|
68
|
+
send(reseedModelPresetContract, { pathPrefix: ws(workspaceId), pathParams: { presetId } }),
|
|
63
69
|
}
|
|
64
70
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { computed } from 'vue'
|
|
2
|
+
import type { ModelPreset } from '~/types/model-presets'
|
|
3
|
+
import { useModelPresetsStore } from '~/stores/modelPresets'
|
|
4
|
+
|
|
5
|
+
export type ModelPresetIssueType = 'outdated' | 'new'
|
|
6
|
+
|
|
7
|
+
/** A built-in model preset that the workspace should reseed (an update, or a new one to add). */
|
|
8
|
+
export interface ModelPresetIssue {
|
|
9
|
+
type: ModelPresetIssueType
|
|
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: ModelPreset | undefined): string {
|
|
22
|
+
if (stored) return stored.name
|
|
23
|
+
// `mdp_claude` -> "claude" — only used until the row is reseeded into existence.
|
|
24
|
+
return id.replace(/^mdp_/, '').replace(/_/g, ' ')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Detect built-in model 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 useModelPresetHealth() {
|
|
36
|
+
const store = useModelPresetsStore()
|
|
37
|
+
|
|
38
|
+
const issues = computed<ModelPresetIssue[]>(() => {
|
|
39
|
+
const out: ModelPresetIssue[] = []
|
|
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
|
@@ -74,6 +74,10 @@ const PipelineHealthModal = defineAsyncComponent(
|
|
|
74
74
|
const MergePresetHealthModal = defineAsyncComponent(
|
|
75
75
|
() => import('~/components/settings/MergePresetHealthModal.vue'),
|
|
76
76
|
)
|
|
77
|
+
// Startup advisory for new / outdated built-in model presets — same once-per-session pattern.
|
|
78
|
+
const ModelPresetHealthModal = defineAsyncComponent(
|
|
79
|
+
() => import('~/components/settings/ModelPresetHealthModal.vue'),
|
|
80
|
+
)
|
|
77
81
|
const IntegrationsHub = defineAsyncComponent(
|
|
78
82
|
() => import('~/components/layout/IntegrationsHub.vue'),
|
|
79
83
|
)
|
|
@@ -192,6 +196,24 @@ watch(
|
|
|
192
196
|
{ immediate: true },
|
|
193
197
|
)
|
|
194
198
|
|
|
199
|
+
// Same advisory for built-in model presets: surface new / outdated ones once per session. Defers
|
|
200
|
+
// to the pipeline + merge-preset advisories when they fire, so at most one modal auto-opens.
|
|
201
|
+
const { hasIssues: modelPresetIssues } = useModelPresetHealth()
|
|
202
|
+
watch(
|
|
203
|
+
() => [workspace.ready, modelPresetIssues.value, ui.pipelineHealthOpen, ui.mergePresetHealthOpen],
|
|
204
|
+
() => {
|
|
205
|
+
if (
|
|
206
|
+
workspace.ready &&
|
|
207
|
+
modelPresetIssues.value &&
|
|
208
|
+
!ui.pipelineHealthOpen &&
|
|
209
|
+
!ui.mergePresetHealthOpen
|
|
210
|
+
) {
|
|
211
|
+
ui.maybeOpenModelPresetHealth()
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
{ immediate: true },
|
|
215
|
+
)
|
|
216
|
+
|
|
195
217
|
// Auto-open the right AI-onboarding dialog once per session: the no-source prompt takes
|
|
196
218
|
// precedence over the preset-mismatch prompt. Honour the per-session dismissed flags so a
|
|
197
219
|
// user who closed the banner isn't re-interrupted, and only auto-open once each (later opens
|
|
@@ -369,6 +391,7 @@ watch(
|
|
|
369
391
|
<FragmentLibraryPanel v-if="ui.fragmentLibraryOpen" />
|
|
370
392
|
<PipelineHealthModal v-if="ui.pipelineHealthOpen" />
|
|
371
393
|
<MergePresetHealthModal v-if="ui.mergePresetHealthOpen" />
|
|
394
|
+
<ModelPresetHealthModal v-if="ui.modelPresetHealthOpen" />
|
|
372
395
|
<IntegrationsHub v-if="ui.integrationsOpen" />
|
|
373
396
|
<PersonalSetupModal v-if="ui.personalSetupOpen" />
|
|
374
397
|
<WorkspaceSettingsPanel v-if="ui.workspaceSettingsOpen" />
|
|
@@ -18,9 +18,18 @@ export const useModelPresetsStore = defineStore('modelPresets', () => {
|
|
|
18
18
|
const api = useApi()
|
|
19
19
|
|
|
20
20
|
const presets = ref<ModelPreset[]>([])
|
|
21
|
+
/**
|
|
22
|
+
* Current built-in catalog versions (`seedModelPresets()`), keyed by preset id, from the
|
|
23
|
+
* workspace snapshot. The keys ARE the set of built-in ids: a stored preset whose id is a
|
|
24
|
+
* key here is a built-in (and is outdated when its `version` is below the catalog value),
|
|
25
|
+
* and a key with no matching stored preset is a NEW built-in the workspace can add. Drives
|
|
26
|
+
* `useModelPresetHealth`.
|
|
27
|
+
*/
|
|
28
|
+
const catalogVersions = ref<Record<string, number>>({})
|
|
21
29
|
|
|
22
|
-
function hydrate(list: ModelPreset[]) {
|
|
30
|
+
function hydrate(list: ModelPreset[], versions?: Record<string, number>) {
|
|
23
31
|
presets.value = [...list].sort((a, b) => a.createdAt - b.createdAt)
|
|
32
|
+
if (versions) catalogVersions.value = versions
|
|
24
33
|
}
|
|
25
34
|
|
|
26
35
|
/** The workspace default (fallback for a task that picks none). */
|
|
@@ -61,5 +70,43 @@ export const useModelPresetsStore = defineStore('modelPresets', () => {
|
|
|
61
70
|
await ws.refresh()
|
|
62
71
|
}
|
|
63
72
|
|
|
64
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Reseed a built-in preset from the backend's current catalog: adopt an updated definition,
|
|
75
|
+
* repair a drifted one, or materialise a NEW built-in that appeared after the workspace was
|
|
76
|
+
* created. The `presetId` is the catalog id (e.g. `mdp_kimi`). Refreshes the snapshot.
|
|
77
|
+
*/
|
|
78
|
+
async function reseed(presetId: string) {
|
|
79
|
+
const ws = useWorkspaceStore()
|
|
80
|
+
const updated = await api.reseedModelPreset(ws.requireId(), presetId)
|
|
81
|
+
await ws.refresh()
|
|
82
|
+
return updated
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Reseed several built-ins in one go, refreshing the snapshot ONCE at the end rather than
|
|
87
|
+
* after every id (each `reseed` refetches the whole board, so a per-id refresh in a loop is
|
|
88
|
+
* wasteful). The POSTs run sequentially so the backend's single-default invariant settles
|
|
89
|
+
* deterministically.
|
|
90
|
+
*/
|
|
91
|
+
async function reseedMany(presetIds: string[]) {
|
|
92
|
+
const ws = useWorkspaceStore()
|
|
93
|
+
for (const presetId of presetIds) {
|
|
94
|
+
await api.reseedModelPreset(ws.requireId(), presetId)
|
|
95
|
+
}
|
|
96
|
+
await ws.refresh()
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
presets,
|
|
101
|
+
catalogVersions,
|
|
102
|
+
defaultPreset,
|
|
103
|
+
resolve,
|
|
104
|
+
modelForKind,
|
|
105
|
+
hydrate,
|
|
106
|
+
create,
|
|
107
|
+
update,
|
|
108
|
+
remove,
|
|
109
|
+
reseed,
|
|
110
|
+
reseedMany,
|
|
111
|
+
}
|
|
65
112
|
})
|
package/app/stores/ui.ts
CHANGED
|
@@ -44,6 +44,11 @@ export const useUiStore = defineStore('ui', () => {
|
|
|
44
44
|
// once per session so it does not re-pop on every snapshot re-hydration (mirrors pipelines).
|
|
45
45
|
const mergePresetHealthOpen = ref(false)
|
|
46
46
|
const mergePresetHealthSeen = ref(false)
|
|
47
|
+
// Model-preset health startup advisory: lists built-ins with a newer catalog version (reseed)
|
|
48
|
+
// and new built-in presets the workspace can add. `modelPresetHealthSeen` gates auto-open to
|
|
49
|
+
// once per session so it does not re-pop on every snapshot re-hydration (mirrors pipelines).
|
|
50
|
+
const modelPresetHealthOpen = ref(false)
|
|
51
|
+
const modelPresetHealthSeen = ref(false)
|
|
47
52
|
const decisionContext = ref<{ instanceId: string; decisionId: string } | null>(null)
|
|
48
53
|
|
|
49
54
|
// Document-source integration modals, keyed by source. `documentImport` and
|
|
@@ -323,6 +328,22 @@ export const useUiStore = defineStore('ui', () => {
|
|
|
323
328
|
mergePresetHealthOpen.value = false
|
|
324
329
|
}
|
|
325
330
|
|
|
331
|
+
/** Auto-open the model-preset health advisory once per session (no-op after it's been shown). */
|
|
332
|
+
function maybeOpenModelPresetHealth() {
|
|
333
|
+
if (modelPresetHealthSeen.value) return
|
|
334
|
+
modelPresetHealthSeen.value = true
|
|
335
|
+
modelPresetHealthOpen.value = true
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function openModelPresetHealth() {
|
|
339
|
+
modelPresetHealthSeen.value = true
|
|
340
|
+
modelPresetHealthOpen.value = true
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function closeModelPresetHealth() {
|
|
344
|
+
modelPresetHealthOpen.value = false
|
|
345
|
+
}
|
|
346
|
+
|
|
326
347
|
function openDecision(instanceId: string, decisionId: string) {
|
|
327
348
|
decisionContext.value = { instanceId, decisionId }
|
|
328
349
|
}
|
|
@@ -820,6 +841,8 @@ export const useUiStore = defineStore('ui', () => {
|
|
|
820
841
|
pipelineHealthSeen,
|
|
821
842
|
mergePresetHealthOpen,
|
|
822
843
|
mergePresetHealthSeen,
|
|
844
|
+
modelPresetHealthOpen,
|
|
845
|
+
modelPresetHealthSeen,
|
|
823
846
|
decisionContext,
|
|
824
847
|
documentConnect,
|
|
825
848
|
documentImport,
|
|
@@ -887,6 +910,9 @@ export const useUiStore = defineStore('ui', () => {
|
|
|
887
910
|
maybeOpenMergePresetHealth,
|
|
888
911
|
openMergePresetHealth,
|
|
889
912
|
closeMergePresetHealth,
|
|
913
|
+
maybeOpenModelPresetHealth,
|
|
914
|
+
openModelPresetHealth,
|
|
915
|
+
closeModelPresetHealth,
|
|
890
916
|
openDecision,
|
|
891
917
|
closeDecision,
|
|
892
918
|
openApprovalDetail,
|
package/app/stores/workspace.ts
CHANGED
|
@@ -127,7 +127,10 @@ export const useWorkspaceStore = defineStore(
|
|
|
127
127
|
useSharedStacksStore().hydrate(snapshot.sharedStacks ?? [])
|
|
128
128
|
useWorkspaceSettingsStore().hydrate(snapshot.settings)
|
|
129
129
|
useAgentConfigStore().hydrate(snapshot.agentConfigCatalog ?? [])
|
|
130
|
-
useModelPresetsStore().hydrate(
|
|
130
|
+
useModelPresetsStore().hydrate(
|
|
131
|
+
snapshot.modelPresets ?? [],
|
|
132
|
+
snapshot.modelPresetCatalogVersions,
|
|
133
|
+
)
|
|
131
134
|
useServiceFragmentDefaultsStore().hydrate(snapshot.serviceFragmentDefaults?.fragmentIds)
|
|
132
135
|
useRecurringPipelinesStore().hydrate(snapshot.recurringPipelines ?? [])
|
|
133
136
|
useInitiativesStore().hydrate(snapshot.initiatives)
|
package/i18n/locales/de.json
CHANGED
|
@@ -4374,6 +4374,25 @@
|
|
|
4374
4374
|
}
|
|
4375
4375
|
}
|
|
4376
4376
|
},
|
|
4377
|
+
"modelPreset": {
|
|
4378
|
+
"health": {
|
|
4379
|
+
"title": "Modell-Preset-Updates",
|
|
4380
|
+
"allValid": "Alle integrierten Modell-Presets sind auf dem neuesten Stand.",
|
|
4381
|
+
"newHeading": "Neue Presets verfügbar",
|
|
4382
|
+
"newDescription": "Neue integrierte Modell-Presets sind verfügbar. Füge sie zur Bibliothek dieses Boards hinzu.",
|
|
4383
|
+
"add": "Hinzufügen",
|
|
4384
|
+
"updatesHeading": "Updates verfügbar",
|
|
4385
|
+
"updatesDescription": "Eine neuere Version dieser integrierten Modell-Presets ist verfügbar. Führe ein erneutes Seeding durch, um sie zu übernehmen (Standard und Reihenfolge bleiben erhalten).",
|
|
4386
|
+
"versionAvailable": "Version {from} → {to} verfügbar.",
|
|
4387
|
+
"reseed": "Erneut seeden",
|
|
4388
|
+
"reseedAll": "Alle aktualisieren ({count})",
|
|
4389
|
+
"dismiss": "Schließen",
|
|
4390
|
+
"done": "Fertig",
|
|
4391
|
+
"toast": {
|
|
4392
|
+
"reseedFailed": "Modell-Preset konnte nicht erneut geseedet werden"
|
|
4393
|
+
}
|
|
4394
|
+
}
|
|
4395
|
+
},
|
|
4377
4396
|
"environmentWizard": {
|
|
4378
4397
|
"title": "Eine Testumgebung einrichten",
|
|
4379
4398
|
"subtitle": "Erkenne, prüfe und speichere ein Docker-Compose-Rezept, damit der Deployer es bereitstellt.",
|
package/i18n/locales/en.json
CHANGED
|
@@ -3269,6 +3269,25 @@
|
|
|
3269
3269
|
}
|
|
3270
3270
|
}
|
|
3271
3271
|
},
|
|
3272
|
+
"modelPreset": {
|
|
3273
|
+
"health": {
|
|
3274
|
+
"title": "Model preset updates",
|
|
3275
|
+
"allValid": "All built-in model presets are up to date.",
|
|
3276
|
+
"newHeading": "New presets available",
|
|
3277
|
+
"newDescription": "New built-in model presets have shipped. Add them to this board's library.",
|
|
3278
|
+
"add": "Add",
|
|
3279
|
+
"updatesHeading": "Updates available",
|
|
3280
|
+
"updatesDescription": "A newer version of these built-in model presets has shipped. Reseed to adopt it (the default and ordering are kept).",
|
|
3281
|
+
"versionAvailable": "Version {from} → {to} available.",
|
|
3282
|
+
"reseed": "Reseed",
|
|
3283
|
+
"reseedAll": "Update all ({count})",
|
|
3284
|
+
"dismiss": "Dismiss",
|
|
3285
|
+
"done": "Done",
|
|
3286
|
+
"toast": {
|
|
3287
|
+
"reseedFailed": "Could not reseed model preset"
|
|
3288
|
+
}
|
|
3289
|
+
}
|
|
3290
|
+
},
|
|
3272
3291
|
"palette": {
|
|
3273
3292
|
"hint": "Click an agent to append it to the pipeline.",
|
|
3274
3293
|
"customAgents": "Custom agents"
|
package/i18n/locales/es.json
CHANGED
|
@@ -4264,6 +4264,25 @@
|
|
|
4264
4264
|
}
|
|
4265
4265
|
}
|
|
4266
4266
|
},
|
|
4267
|
+
"modelPreset": {
|
|
4268
|
+
"health": {
|
|
4269
|
+
"title": "Actualizaciones de presets de modelo",
|
|
4270
|
+
"allValid": "Todos los presets de modelo integrados están actualizados.",
|
|
4271
|
+
"newHeading": "Nuevos presets disponibles",
|
|
4272
|
+
"newDescription": "Hay nuevos presets de modelo integrados. Añádelos a la biblioteca de este tablero.",
|
|
4273
|
+
"add": "Añadir",
|
|
4274
|
+
"updatesHeading": "Actualizaciones disponibles",
|
|
4275
|
+
"updatesDescription": "Hay una versión más reciente de estos presets de modelo integrados. Regenera para adoptarla (se conservan el predeterminado y el orden).",
|
|
4276
|
+
"versionAvailable": "Versión {from} → {to} disponible.",
|
|
4277
|
+
"reseed": "Regenerar",
|
|
4278
|
+
"reseedAll": "Actualizar todos ({count})",
|
|
4279
|
+
"dismiss": "Descartar",
|
|
4280
|
+
"done": "Hecho",
|
|
4281
|
+
"toast": {
|
|
4282
|
+
"reseedFailed": "No se pudo regenerar el preset de modelo"
|
|
4283
|
+
}
|
|
4284
|
+
}
|
|
4285
|
+
},
|
|
4267
4286
|
"initiative": {
|
|
4268
4287
|
"create": {
|
|
4269
4288
|
"title": "Crear iniciativa",
|
package/i18n/locales/fr.json
CHANGED
|
@@ -4264,6 +4264,25 @@
|
|
|
4264
4264
|
}
|
|
4265
4265
|
}
|
|
4266
4266
|
},
|
|
4267
|
+
"modelPreset": {
|
|
4268
|
+
"health": {
|
|
4269
|
+
"title": "Mises à jour des presets de modèle",
|
|
4270
|
+
"allValid": "Tous les presets de modèle intégrés sont à jour.",
|
|
4271
|
+
"newHeading": "Nouveaux presets disponibles",
|
|
4272
|
+
"newDescription": "De nouveaux presets de modèle intégrés sont arrivés. Ajoutez-les à la bibliothèque de ce tableau.",
|
|
4273
|
+
"add": "Ajouter",
|
|
4274
|
+
"updatesHeading": "Mises à jour disponibles",
|
|
4275
|
+
"updatesDescription": "Une version plus récente de ces presets de modèle intégrés est arrivée. Régénérez pour l'adopter (le preset par défaut et l'ordre sont conservés).",
|
|
4276
|
+
"versionAvailable": "Version {from} → {to} disponible.",
|
|
4277
|
+
"reseed": "Régénérer",
|
|
4278
|
+
"reseedAll": "Tout mettre à jour ({count})",
|
|
4279
|
+
"dismiss": "Ignorer",
|
|
4280
|
+
"done": "Terminé",
|
|
4281
|
+
"toast": {
|
|
4282
|
+
"reseedFailed": "Impossible de régénérer le preset de modèle"
|
|
4283
|
+
}
|
|
4284
|
+
}
|
|
4285
|
+
},
|
|
4267
4286
|
"initiative": {
|
|
4268
4287
|
"create": {
|
|
4269
4288
|
"title": "Creer une initiative",
|
package/i18n/locales/he.json
CHANGED
|
@@ -4275,6 +4275,25 @@
|
|
|
4275
4275
|
}
|
|
4276
4276
|
}
|
|
4277
4277
|
},
|
|
4278
|
+
"modelPreset": {
|
|
4279
|
+
"health": {
|
|
4280
|
+
"title": "עדכוני קביעות מודל",
|
|
4281
|
+
"allValid": "כל קביעות המודל המובנות מעודכנות.",
|
|
4282
|
+
"newHeading": "קביעות חדשות זמינות",
|
|
4283
|
+
"newDescription": "הגיעו קביעות מודל מובנות חדשות. הוסף אותן לספריית הלוח הזה.",
|
|
4284
|
+
"add": "הוסף",
|
|
4285
|
+
"updatesHeading": "עדכונים זמינים",
|
|
4286
|
+
"updatesDescription": "גרסה חדשה יותר של קביעות המודל המובנות האלה הגיעה. זרע מחדש כדי לאמץ אותה (ברירת המחדל והסדר נשמרים).",
|
|
4287
|
+
"versionAvailable": "גרסה {from} → {to} זמינה.",
|
|
4288
|
+
"reseed": "זרע מחדש",
|
|
4289
|
+
"reseedAll": "עדכן הכל ({count})",
|
|
4290
|
+
"dismiss": "התעלם",
|
|
4291
|
+
"done": "בוצע",
|
|
4292
|
+
"toast": {
|
|
4293
|
+
"reseedFailed": "לא ניתן לזרוע מחדש את קביעת המודל"
|
|
4294
|
+
}
|
|
4295
|
+
}
|
|
4296
|
+
},
|
|
4278
4297
|
"initiative": {
|
|
4279
4298
|
"create": {
|
|
4280
4299
|
"title": "יצירת יוזמה",
|
package/i18n/locales/it.json
CHANGED
|
@@ -4374,6 +4374,25 @@
|
|
|
4374
4374
|
}
|
|
4375
4375
|
}
|
|
4376
4376
|
},
|
|
4377
|
+
"modelPreset": {
|
|
4378
|
+
"health": {
|
|
4379
|
+
"title": "Aggiornamenti dei preset di modello",
|
|
4380
|
+
"allValid": "Tutti i preset di modello integrati sono aggiornati.",
|
|
4381
|
+
"newHeading": "Nuovi preset disponibili",
|
|
4382
|
+
"newDescription": "Sono stati rilasciati nuovi preset di modello integrati. Aggiungili alla libreria di questa board.",
|
|
4383
|
+
"add": "Aggiungi",
|
|
4384
|
+
"updatesHeading": "Aggiornamenti disponibili",
|
|
4385
|
+
"updatesDescription": "È stata rilasciata una versione più recente di questi preset di modello integrati. Ripristina i valori iniziali per adottarla (il predefinito e l'ordinamento vengono mantenuti).",
|
|
4386
|
+
"versionAvailable": "Versione {from} → {to} disponibile.",
|
|
4387
|
+
"reseed": "Ripristina",
|
|
4388
|
+
"reseedAll": "Aggiorna tutti ({count})",
|
|
4389
|
+
"dismiss": "Ignora",
|
|
4390
|
+
"done": "Fatto",
|
|
4391
|
+
"toast": {
|
|
4392
|
+
"reseedFailed": "Impossibile ripristinare il preset di modello"
|
|
4393
|
+
}
|
|
4394
|
+
}
|
|
4395
|
+
},
|
|
4377
4396
|
"environmentWizard": {
|
|
4378
4397
|
"title": "Configura un ambiente di test",
|
|
4379
4398
|
"subtitle": "Rileva, rivedi e salva una ricetta Docker Compose in modo che il Deployer la esegua.",
|
package/i18n/locales/ja.json
CHANGED
|
@@ -4276,6 +4276,25 @@
|
|
|
4276
4276
|
}
|
|
4277
4277
|
}
|
|
4278
4278
|
},
|
|
4279
|
+
"modelPreset": {
|
|
4280
|
+
"health": {
|
|
4281
|
+
"title": "モデルプリセットの更新",
|
|
4282
|
+
"allValid": "組み込みのモデルプリセットはすべて最新です。",
|
|
4283
|
+
"newHeading": "新しいプリセットがあります",
|
|
4284
|
+
"newDescription": "新しい組み込みモデルプリセットが追加されました。このボードのライブラリに追加してください。",
|
|
4285
|
+
"add": "追加",
|
|
4286
|
+
"updatesHeading": "更新あり",
|
|
4287
|
+
"updatesDescription": "これらの組み込みモデルプリセットの新しいバージョンがあります。再シードして取り込みます(既定と並び順は保持されます)。",
|
|
4288
|
+
"versionAvailable": "バージョン {from} → {to} が利用可能です。",
|
|
4289
|
+
"reseed": "再シード",
|
|
4290
|
+
"reseedAll": "すべて更新 ({count})",
|
|
4291
|
+
"dismiss": "閉じる",
|
|
4292
|
+
"done": "完了",
|
|
4293
|
+
"toast": {
|
|
4294
|
+
"reseedFailed": "モデルプリセットを再シードできませんでした"
|
|
4295
|
+
}
|
|
4296
|
+
}
|
|
4297
|
+
},
|
|
4279
4298
|
"initiative": {
|
|
4280
4299
|
"create": {
|
|
4281
4300
|
"title": "イニシアチブを作成",
|
package/i18n/locales/pl.json
CHANGED
|
@@ -4264,6 +4264,25 @@
|
|
|
4264
4264
|
}
|
|
4265
4265
|
}
|
|
4266
4266
|
},
|
|
4267
|
+
"modelPreset": {
|
|
4268
|
+
"health": {
|
|
4269
|
+
"title": "Aktualizacje presetów modelu",
|
|
4270
|
+
"allValid": "Wszystkie wbudowane presety modelu są aktualne.",
|
|
4271
|
+
"newHeading": "Dostępne nowe presety",
|
|
4272
|
+
"newDescription": "Pojawiły się nowe wbudowane presety modelu. Dodaj je do biblioteki tej tablicy.",
|
|
4273
|
+
"add": "Dodaj",
|
|
4274
|
+
"updatesHeading": "Dostępne aktualizacje",
|
|
4275
|
+
"updatesDescription": "Dostępna jest nowsza wersja tych wbudowanych presetów modelu. Zregeneruj, aby ją przyjąć (domyślny i kolejność są zachowane).",
|
|
4276
|
+
"versionAvailable": "Dostępna wersja {from} → {to}.",
|
|
4277
|
+
"reseed": "Zregeneruj",
|
|
4278
|
+
"reseedAll": "Zaktualizuj wszystkie ({count})",
|
|
4279
|
+
"dismiss": "Odrzuć",
|
|
4280
|
+
"done": "Gotowe",
|
|
4281
|
+
"toast": {
|
|
4282
|
+
"reseedFailed": "Nie udało się zregenerować presetu modelu"
|
|
4283
|
+
}
|
|
4284
|
+
}
|
|
4285
|
+
},
|
|
4267
4286
|
"initiative": {
|
|
4268
4287
|
"create": {
|
|
4269
4288
|
"title": "Utworz inicjatywe",
|
package/i18n/locales/tr.json
CHANGED
|
@@ -4276,6 +4276,25 @@
|
|
|
4276
4276
|
}
|
|
4277
4277
|
}
|
|
4278
4278
|
},
|
|
4279
|
+
"modelPreset": {
|
|
4280
|
+
"health": {
|
|
4281
|
+
"title": "Model ön ayarı güncellemeleri",
|
|
4282
|
+
"allValid": "Tüm yerleşik model ön ayarları güncel.",
|
|
4283
|
+
"newHeading": "Yeni ön ayarlar mevcut",
|
|
4284
|
+
"newDescription": "Yeni yerleşik model ön ayarları geldi. Bu panonun kütüphanesine ekleyin.",
|
|
4285
|
+
"add": "Ekle",
|
|
4286
|
+
"updatesHeading": "Güncellemeler mevcut",
|
|
4287
|
+
"updatesDescription": "Bu yerleşik model ön ayarlarının daha yeni bir sürümü geldi. Benimsemek için yeniden tohumlayın (varsayılan ve sıralama korunur).",
|
|
4288
|
+
"versionAvailable": "Sürüm {from} → {to} mevcut.",
|
|
4289
|
+
"reseed": "Yeniden tohumla",
|
|
4290
|
+
"reseedAll": "Tümünü güncelle ({count})",
|
|
4291
|
+
"dismiss": "Yoksay",
|
|
4292
|
+
"done": "Tamam",
|
|
4293
|
+
"toast": {
|
|
4294
|
+
"reseedFailed": "Model ön ayarı yeniden tohumlanamadı"
|
|
4295
|
+
}
|
|
4296
|
+
}
|
|
4297
|
+
},
|
|
4279
4298
|
"initiative": {
|
|
4280
4299
|
"create": {
|
|
4281
4300
|
"title": "Girisim olustur",
|
package/i18n/locales/uk.json
CHANGED
|
@@ -4264,6 +4264,25 @@
|
|
|
4264
4264
|
}
|
|
4265
4265
|
}
|
|
4266
4266
|
},
|
|
4267
|
+
"modelPreset": {
|
|
4268
|
+
"health": {
|
|
4269
|
+
"title": "Оновлення пресетів моделі",
|
|
4270
|
+
"allValid": "Усі вбудовані пресети моделі актуальні.",
|
|
4271
|
+
"newHeading": "Доступні нові пресети",
|
|
4272
|
+
"newDescription": "З'явилися нові вбудовані пресети моделі. Додайте їх до бібліотеки цієї дошки.",
|
|
4273
|
+
"add": "Додати",
|
|
4274
|
+
"updatesHeading": "Доступні оновлення",
|
|
4275
|
+
"updatesDescription": "Доступна новіша версія цих вбудованих пресетів моделі. Перегенеруйте, щоб застосувати її (стандартний пресет і порядок збережено).",
|
|
4276
|
+
"versionAvailable": "Доступна версія {from} → {to}.",
|
|
4277
|
+
"reseed": "Перегенерувати",
|
|
4278
|
+
"reseedAll": "Оновити всі ({count})",
|
|
4279
|
+
"dismiss": "Відхилити",
|
|
4280
|
+
"done": "Готово",
|
|
4281
|
+
"toast": {
|
|
4282
|
+
"reseedFailed": "Не вдалося перегенерувати пресет моделі"
|
|
4283
|
+
}
|
|
4284
|
+
}
|
|
4285
|
+
},
|
|
4267
4286
|
"initiative": {
|
|
4268
4287
|
"create": {
|
|
4269
4288
|
"title": "Створити ініціативу",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.108.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.119.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@toad-contracts/testing": "0.3.2",
|