@cat-factory/app 0.146.1 → 0.146.3
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/fragments/FragmentSelector.vue +101 -37
- package/app/utils/fragmentPicker.spec.ts +22 -1
- package/app/utils/fragmentPicker.ts +30 -11
- package/i18n/locales/de.json +3 -1
- package/i18n/locales/en.json +3 -1
- package/i18n/locales/es.json +3 -1
- package/i18n/locales/fr.json +3 -1
- package/i18n/locales/he.json +3 -1
- package/i18n/locales/it.json +3 -1
- package/i18n/locales/ja.json +3 -1
- package/i18n/locales/pl.json +3 -1
- package/i18n/locales/tr.json +3 -1
- package/i18n/locales/uk.json +3 -1
- package/package.json +2 -2
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
// Shared best-practice prompt-fragment picker: a category-grouped
|
|
3
|
-
// to the fragment library) plus the currently-selected fragments as removable badges.
|
|
2
|
+
// Shared best-practice prompt-fragment picker: a category-grouped MULTI-SELECT popover (with links
|
|
3
|
+
// out to the fragment library) plus the currently-selected fragments as removable badges.
|
|
4
|
+
// Selecting a row TOGGLES it and leaves the list open, so several fragments can be picked (and
|
|
5
|
+
// unpicked) in one visit; a dedicated "Done" button closes the panel.
|
|
4
6
|
// Presentational + `v-model`-driven — the caller owns WHERE the selection lives (a task's
|
|
5
7
|
// `fragmentIds`, a service's `serviceFragmentIds`, or a not-yet-created task's local draft) and
|
|
6
8
|
// binds the id list. Authored once and reused by the create-task form and the task/service
|
|
7
9
|
// inspectors so the three pickers can't drift. Ids the catalog no longer resolves still render
|
|
8
10
|
// (labelled by their raw id) so they stay visible and removable.
|
|
9
|
-
import type { DropdownMenuItem } from '@nuxt/ui'
|
|
10
11
|
import type { PromptFragment } from '~/types/domain'
|
|
11
|
-
import {
|
|
12
|
+
import { buildFragmentCategoryGroups } from '~/utils/fragmentPicker'
|
|
12
13
|
|
|
13
14
|
const props = withDefaults(
|
|
14
15
|
defineProps<{
|
|
@@ -30,6 +31,8 @@ const ui = useUiStore()
|
|
|
30
31
|
const accounts = useAccountsStore()
|
|
31
32
|
const { t } = useI18n()
|
|
32
33
|
|
|
34
|
+
const open = ref(false)
|
|
35
|
+
|
|
33
36
|
// The catalog is per-board and invalidated on a workspace switch; (re)load it lazily — a no-op
|
|
34
37
|
// while current.
|
|
35
38
|
onMounted(() => fragments.ensureLoaded())
|
|
@@ -38,39 +41,18 @@ const selectedFragments = computed(() =>
|
|
|
38
41
|
props.modelValue.map((id) => fragments.getFragment(id) ?? { id, title: id, summary: '' }),
|
|
39
42
|
)
|
|
40
43
|
|
|
41
|
-
|
|
42
|
-
// (board tier always; account tier when accounts are enabled). Open to every member.
|
|
43
|
-
const manageItems = computed<DropdownMenuItem[]>(() => {
|
|
44
|
-
const items: DropdownMenuItem[] = [
|
|
45
|
-
{
|
|
46
|
-
label: t('inspector.fragments.manageBoard'),
|
|
47
|
-
icon: 'i-lucide-book-marked',
|
|
48
|
-
onSelect: () => ui.openFragmentLibrary(),
|
|
49
|
-
},
|
|
50
|
-
]
|
|
51
|
-
if (accounts.enabled) {
|
|
52
|
-
items.push({
|
|
53
|
-
label: t('inspector.fragments.manageAccount'),
|
|
54
|
-
icon: 'i-lucide-users',
|
|
55
|
-
onSelect: () => ui.openAccountSettings('fragments'),
|
|
56
|
-
})
|
|
57
|
-
}
|
|
58
|
-
return items
|
|
59
|
-
})
|
|
44
|
+
const selectedSet = computed(() => new Set(props.modelValue))
|
|
60
45
|
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
const
|
|
64
|
-
const selected = new Set(props.modelValue)
|
|
65
|
-
return [
|
|
66
|
-
...buildFragmentPickerGroups(props.pool, (id) => selected.has(id), addFragment),
|
|
67
|
-
manageItems.value,
|
|
68
|
-
]
|
|
69
|
-
})
|
|
46
|
+
// Pool fragments bucketed into labelled per-category sections. Selected rows stay in the list so
|
|
47
|
+
// they can be unpicked in place (a check marks the current selection).
|
|
48
|
+
const categoryGroups = computed(() => buildFragmentCategoryGroups(props.pool))
|
|
70
49
|
|
|
71
|
-
function
|
|
72
|
-
if (props.modelValue.includes(id))
|
|
73
|
-
|
|
50
|
+
function toggleFragment(id: string) {
|
|
51
|
+
if (props.modelValue.includes(id)) {
|
|
52
|
+
removeFragment(id)
|
|
53
|
+
} else {
|
|
54
|
+
emit('update:modelValue', [...props.modelValue, id])
|
|
55
|
+
}
|
|
74
56
|
}
|
|
75
57
|
|
|
76
58
|
function removeFragment(id: string) {
|
|
@@ -79,6 +61,16 @@ function removeFragment(id: string) {
|
|
|
79
61
|
props.modelValue.filter((x) => x !== id),
|
|
80
62
|
)
|
|
81
63
|
}
|
|
64
|
+
|
|
65
|
+
function manageBoard() {
|
|
66
|
+
open.value = false
|
|
67
|
+
ui.openFragmentLibrary()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function manageAccount() {
|
|
71
|
+
open.value = false
|
|
72
|
+
ui.openAccountSettings('fragments')
|
|
73
|
+
}
|
|
82
74
|
</script>
|
|
83
75
|
|
|
84
76
|
<template>
|
|
@@ -88,7 +80,7 @@ function removeFragment(id: string) {
|
|
|
88
80
|
{{ label }}
|
|
89
81
|
</span>
|
|
90
82
|
<span v-else />
|
|
91
|
-
<
|
|
83
|
+
<UPopover v-model:open="open" :content="{ align: 'end' }">
|
|
92
84
|
<UButton
|
|
93
85
|
size="xs"
|
|
94
86
|
variant="ghost"
|
|
@@ -97,7 +89,79 @@ function removeFragment(id: string) {
|
|
|
97
89
|
trailing-icon="i-lucide-chevron-down"
|
|
98
90
|
data-testid="fragment-add"
|
|
99
91
|
/>
|
|
100
|
-
|
|
92
|
+
|
|
93
|
+
<template #content>
|
|
94
|
+
<div
|
|
95
|
+
class="flex max-h-[24rem] w-[min(22rem,92vw)] flex-col"
|
|
96
|
+
data-testid="fragment-picker-panel"
|
|
97
|
+
>
|
|
98
|
+
<div class="min-h-0 flex-1 overflow-y-auto p-1">
|
|
99
|
+
<template v-if="categoryGroups.length">
|
|
100
|
+
<div v-for="group in categoryGroups" :key="group.category">
|
|
101
|
+
<p
|
|
102
|
+
class="px-2 pb-0.5 pt-1.5 text-[11px] font-semibold uppercase tracking-wide text-slate-500"
|
|
103
|
+
>
|
|
104
|
+
{{ group.category }}
|
|
105
|
+
</p>
|
|
106
|
+
<button
|
|
107
|
+
v-for="f in group.fragments"
|
|
108
|
+
:key="f.id"
|
|
109
|
+
type="button"
|
|
110
|
+
class="flex w-full items-center gap-2 rounded px-2 py-1.5 text-start text-sm hover:bg-slate-800/60"
|
|
111
|
+
:class="selectedSet.has(f.id) ? 'text-slate-100' : 'text-slate-300'"
|
|
112
|
+
:title="f.summary"
|
|
113
|
+
:data-testid="`fragment-option-${f.id}`"
|
|
114
|
+
:aria-pressed="selectedSet.has(f.id)"
|
|
115
|
+
@click="toggleFragment(f.id)"
|
|
116
|
+
>
|
|
117
|
+
<UIcon
|
|
118
|
+
:name="selectedSet.has(f.id) ? 'i-lucide-check' : 'i-lucide-plus'"
|
|
119
|
+
class="h-4 w-4 shrink-0"
|
|
120
|
+
:class="selectedSet.has(f.id) ? 'text-primary-400' : 'text-slate-500'"
|
|
121
|
+
/>
|
|
122
|
+
<span class="flex-1 truncate">{{ f.title }}</span>
|
|
123
|
+
</button>
|
|
124
|
+
</div>
|
|
125
|
+
</template>
|
|
126
|
+
<p v-else class="px-2 py-3 text-[12px] text-slate-500">
|
|
127
|
+
{{ t('inspector.fragments.pickerEmpty') }}
|
|
128
|
+
</p>
|
|
129
|
+
|
|
130
|
+
<div class="mt-1 border-t border-slate-800 pt-1">
|
|
131
|
+
<button
|
|
132
|
+
type="button"
|
|
133
|
+
class="flex w-full items-center gap-2 rounded px-2 py-1.5 text-start text-sm text-slate-300 hover:bg-slate-800/60"
|
|
134
|
+
@click="manageBoard"
|
|
135
|
+
>
|
|
136
|
+
<UIcon name="i-lucide-book-marked" class="h-4 w-4 shrink-0 text-slate-400" />
|
|
137
|
+
<span class="flex-1 truncate">{{ t('inspector.fragments.manageBoard') }}</span>
|
|
138
|
+
</button>
|
|
139
|
+
<button
|
|
140
|
+
v-if="accounts.enabled"
|
|
141
|
+
type="button"
|
|
142
|
+
class="flex w-full items-center gap-2 rounded px-2 py-1.5 text-start text-sm text-slate-300 hover:bg-slate-800/60"
|
|
143
|
+
@click="manageAccount"
|
|
144
|
+
>
|
|
145
|
+
<UIcon name="i-lucide-users" class="h-4 w-4 shrink-0 text-slate-400" />
|
|
146
|
+
<span class="flex-1 truncate">{{ t('inspector.fragments.manageAccount') }}</span>
|
|
147
|
+
</button>
|
|
148
|
+
</div>
|
|
149
|
+
</div>
|
|
150
|
+
|
|
151
|
+
<div class="flex justify-end border-t border-slate-800 p-1.5">
|
|
152
|
+
<UButton
|
|
153
|
+
size="xs"
|
|
154
|
+
color="neutral"
|
|
155
|
+
variant="soft"
|
|
156
|
+
data-testid="fragment-picker-done"
|
|
157
|
+
@click="open = false"
|
|
158
|
+
>
|
|
159
|
+
{{ t('inspector.fragments.done') }}
|
|
160
|
+
</UButton>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
</template>
|
|
164
|
+
</UPopover>
|
|
101
165
|
</div>
|
|
102
166
|
<div v-if="selectedFragments.length" class="flex flex-wrap gap-1">
|
|
103
167
|
<UBadge
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest'
|
|
2
2
|
import type { PromptFragment } from '~/types/domain'
|
|
3
|
-
import { buildFragmentPickerGroups } from './fragmentPicker'
|
|
3
|
+
import { buildFragmentCategoryGroups, buildFragmentPickerGroups } from './fragmentPicker'
|
|
4
4
|
|
|
5
5
|
const frag = (id: string, category: string, title = id): PromptFragment =>
|
|
6
6
|
({ id, version: '1.0.0', title, category, summary: '', body: '' }) as PromptFragment
|
|
@@ -58,3 +58,24 @@ describe('buildFragmentPickerGroups', () => {
|
|
|
58
58
|
expect(picked).toEqual(['node.best-practices'])
|
|
59
59
|
})
|
|
60
60
|
})
|
|
61
|
+
|
|
62
|
+
describe('buildFragmentCategoryGroups', () => {
|
|
63
|
+
it('buckets every fragment by category in first-appearance order, keeping pool order within', () => {
|
|
64
|
+
const groups = buildFragmentCategoryGroups(pool)
|
|
65
|
+
expect(groups.map((g) => g.category)).toEqual(['Node', 'Writing style'])
|
|
66
|
+
expect(groups[0]!.fragments.map((f) => f.id)).toEqual([
|
|
67
|
+
'node.best-practices',
|
|
68
|
+
'node.performance',
|
|
69
|
+
])
|
|
70
|
+
expect(groups[1]!.fragments.map((f) => f.id)).toEqual([
|
|
71
|
+
'style.anti-llmisms',
|
|
72
|
+
'style.concise-actionable',
|
|
73
|
+
])
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it('keeps selected fragments in their bucket (multi-select toggles in place, never hides)', () => {
|
|
77
|
+
// Unlike the dropdown builder, the category grouping does no selection filtering.
|
|
78
|
+
const groups = buildFragmentCategoryGroups(pool)
|
|
79
|
+
expect(groups.flatMap((g) => g.fragments)).toHaveLength(pool.length)
|
|
80
|
+
})
|
|
81
|
+
})
|
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
import type { DropdownMenuItem } from '@nuxt/ui'
|
|
2
2
|
import type { PromptFragment } from '~/types/domain'
|
|
3
3
|
|
|
4
|
+
/** One category bucket: its heading plus the pool fragments that fall under it, in pool order. */
|
|
5
|
+
export interface FragmentCategoryGroup {
|
|
6
|
+
category: string
|
|
7
|
+
fragments: PromptFragment[]
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Bucket the pool fragments by `category`, preserving first-appearance category order and
|
|
12
|
+
* per-category pool order. Unlike {@link buildFragmentPickerGroups} this keeps ALL fragments
|
|
13
|
+
* (selected included) and returns the raw fragments, so a multi-select surface can render each
|
|
14
|
+
* as a toggle that stays visible whether or not it is currently picked.
|
|
15
|
+
*/
|
|
16
|
+
export function buildFragmentCategoryGroups(pool: PromptFragment[]): FragmentCategoryGroup[] {
|
|
17
|
+
const groups = new Map<string, PromptFragment[]>()
|
|
18
|
+
for (const f of pool) {
|
|
19
|
+
const items = groups.get(f.category) ?? []
|
|
20
|
+
items.push(f)
|
|
21
|
+
groups.set(f.category, items)
|
|
22
|
+
}
|
|
23
|
+
return [...groups.entries()].map(([category, fragments]) => ({ category, fragments }))
|
|
24
|
+
}
|
|
25
|
+
|
|
4
26
|
/**
|
|
5
27
|
* Build the category-grouped groups for a fragment "add" dropdown: the pool fragments not
|
|
6
28
|
* already selected, bucketed by `category`, each bucket prefixed with a non-interactive
|
|
@@ -18,15 +40,12 @@ export function buildFragmentPickerGroups(
|
|
|
18
40
|
isSelected: (id: string) => boolean,
|
|
19
41
|
onSelect: (id: string) => void,
|
|
20
42
|
): DropdownMenuItem[][] {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
{ type: 'label', label: category },
|
|
30
|
-
...items,
|
|
31
|
-
])
|
|
43
|
+
return buildFragmentCategoryGroups(pool)
|
|
44
|
+
.map(({ category, fragments }): DropdownMenuItem[] => {
|
|
45
|
+
const items = fragments
|
|
46
|
+
.filter((f) => !isSelected(f.id))
|
|
47
|
+
.map((f): DropdownMenuItem => ({ label: f.title, onSelect: () => onSelect(f.id) }))
|
|
48
|
+
return items.length ? [{ type: 'label', label: category }, ...items] : []
|
|
49
|
+
})
|
|
50
|
+
.filter((group) => group.length > 0)
|
|
32
51
|
}
|
package/i18n/locales/de.json
CHANGED
|
@@ -931,7 +931,9 @@
|
|
|
931
931
|
"serviceHint": "Programmierstandards für den gesamten Service. Der Inhalt jedes ausgewählten Fragments wird dem Prompt jedes code-bewussten Agents hinzugefügt, der an Aufgaben unter diesem Service arbeitet.",
|
|
932
932
|
"serviceEmpty": "Keine. Code-bewusste Agents dieses Service folgen ihren Standardvorgaben.",
|
|
933
933
|
"manageBoard": "Fragment-Bibliothek dieses Boards verwalten…",
|
|
934
|
-
"manageAccount": "Konto-Fragmente verwalten…"
|
|
934
|
+
"manageAccount": "Konto-Fragmente verwalten…",
|
|
935
|
+
"done": "Fertig",
|
|
936
|
+
"pickerEmpty": "Keine Fragmente verfügbar."
|
|
935
937
|
},
|
|
936
938
|
"frontendConfig": {
|
|
937
939
|
"title": "Frontend",
|
package/i18n/locales/en.json
CHANGED
|
@@ -706,7 +706,9 @@
|
|
|
706
706
|
"serviceHint": "Programming standards for the whole service. The content of each selected fragment is added to the prompt of every code-aware agent working on tasks under this service.",
|
|
707
707
|
"serviceEmpty": "None. Code-aware agents on this service follow their default guidance.",
|
|
708
708
|
"manageBoard": "Manage this board's fragment library…",
|
|
709
|
-
"manageAccount": "Manage account fragments…"
|
|
709
|
+
"manageAccount": "Manage account fragments…",
|
|
710
|
+
"done": "Done",
|
|
711
|
+
"pickerEmpty": "No fragments available."
|
|
710
712
|
},
|
|
711
713
|
"frontendConfig": {
|
|
712
714
|
"title": "Frontend",
|
package/i18n/locales/es.json
CHANGED
|
@@ -649,7 +649,9 @@
|
|
|
649
649
|
"serviceHint": "Estándares de programación para todo el servicio. El contenido de cada fragmento seleccionado se añade al prompt de cada agente que conoce el código y trabaja en tareas de este servicio.",
|
|
650
650
|
"serviceEmpty": "Ninguna. Los agentes que conocen el código en este servicio siguen su guía predeterminada.",
|
|
651
651
|
"manageBoard": "Gestionar la biblioteca de fragmentos de este tablero…",
|
|
652
|
-
"manageAccount": "Gestionar los fragmentos de la cuenta…"
|
|
652
|
+
"manageAccount": "Gestionar los fragmentos de la cuenta…",
|
|
653
|
+
"done": "Listo",
|
|
654
|
+
"pickerEmpty": "No hay fragmentos disponibles."
|
|
653
655
|
},
|
|
654
656
|
"frontendConfig": {
|
|
655
657
|
"title": "Frontend",
|
package/i18n/locales/fr.json
CHANGED
|
@@ -649,7 +649,9 @@
|
|
|
649
649
|
"serviceHint": "Normes de programmation pour tout le service. Le contenu de chaque fragment sélectionné est ajouté au prompt de chaque agent conscient du code travaillant sur les tâches de ce service.",
|
|
650
650
|
"serviceEmpty": "Aucune. Les agents conscients du code sur ce service suivent leurs consignes par défaut.",
|
|
651
651
|
"manageBoard": "Gérer la bibliothèque de fragments de ce tableau…",
|
|
652
|
-
"manageAccount": "Gérer les fragments du compte…"
|
|
652
|
+
"manageAccount": "Gérer les fragments du compte…",
|
|
653
|
+
"done": "Terminé",
|
|
654
|
+
"pickerEmpty": "Aucun fragment disponible."
|
|
653
655
|
},
|
|
654
656
|
"frontendConfig": {
|
|
655
657
|
"title": "Frontend",
|
package/i18n/locales/he.json
CHANGED
|
@@ -649,7 +649,9 @@
|
|
|
649
649
|
"serviceHint": "תקני תכנות לכל השירות. התוכן של כל פרגמנט שנבחר מתווסף לפרומפט של כל סוכן מודע-קוד שעובד על משימות תחת שירות זה.",
|
|
650
650
|
"serviceEmpty": "אין. סוכנים מודעי-קוד בשירות זה פועלים לפי ההנחיות המוגדרות כברירת מחדל.",
|
|
651
651
|
"manageBoard": "נהל את ספריית הקטעים של לוח זה…",
|
|
652
|
-
"manageAccount": "נהל קטעי חשבון…"
|
|
652
|
+
"manageAccount": "נהל קטעי חשבון…",
|
|
653
|
+
"done": "סיום",
|
|
654
|
+
"pickerEmpty": "אין קטעים זמינים."
|
|
653
655
|
},
|
|
654
656
|
"frontendConfig": {
|
|
655
657
|
"title": "Frontend",
|
package/i18n/locales/it.json
CHANGED
|
@@ -931,7 +931,9 @@
|
|
|
931
931
|
"serviceHint": "Standard di programmazione per l'intero servizio. Il contenuto di ogni frammento selezionato viene aggiunto al prompt di ogni agente code-aware che lavora sulle attivita' di questo servizio.",
|
|
932
932
|
"serviceEmpty": "Nessuno. Gli agenti code-aware su questo servizio seguono le loro linee guida predefinite.",
|
|
933
933
|
"manageBoard": "Gestisci la libreria di frammenti di questa board…",
|
|
934
|
-
"manageAccount": "Gestisci i frammenti dell'account…"
|
|
934
|
+
"manageAccount": "Gestisci i frammenti dell'account…",
|
|
935
|
+
"done": "Fatto",
|
|
936
|
+
"pickerEmpty": "Nessun frammento disponibile."
|
|
935
937
|
},
|
|
936
938
|
"frontendConfig": {
|
|
937
939
|
"title": "Frontend",
|
package/i18n/locales/ja.json
CHANGED
|
@@ -649,7 +649,9 @@
|
|
|
649
649
|
"serviceHint": "サービス全体のプログラミング標準です。選択した各フラグメントの内容は、このサービスのタスクに取り組むコード対応エージェントすべてのプロンプトに追加されます。",
|
|
650
650
|
"serviceEmpty": "なし。このサービスのコード対応エージェントはデフォルトのガイダンスに従います。",
|
|
651
651
|
"manageBoard": "このボードのフラグメントライブラリを管理…",
|
|
652
|
-
"manageAccount": "アカウントのフラグメントを管理…"
|
|
652
|
+
"manageAccount": "アカウントのフラグメントを管理…",
|
|
653
|
+
"done": "完了",
|
|
654
|
+
"pickerEmpty": "利用可能なフラグメントがありません。"
|
|
653
655
|
},
|
|
654
656
|
"frontendConfig": {
|
|
655
657
|
"title": "フロントエンド",
|
package/i18n/locales/pl.json
CHANGED
|
@@ -649,7 +649,9 @@
|
|
|
649
649
|
"serviceHint": "Standardy programowania dla całej usługi. Treść każdego wybranego fragmentu jest dodawana do promptu każdego agenta świadomego kodu pracującego nad zadaniami tej usługi.",
|
|
650
650
|
"serviceEmpty": "Brak. Agenci świadomi kodu w tej usłudze stosują swoje domyślne wytyczne.",
|
|
651
651
|
"manageBoard": "Zarządzaj biblioteką fragmentów tej tablicy…",
|
|
652
|
-
"manageAccount": "Zarządzaj fragmentami konta…"
|
|
652
|
+
"manageAccount": "Zarządzaj fragmentami konta…",
|
|
653
|
+
"done": "Gotowe",
|
|
654
|
+
"pickerEmpty": "Brak dostępnych fragmentów."
|
|
653
655
|
},
|
|
654
656
|
"frontendConfig": {
|
|
655
657
|
"title": "Frontend",
|
package/i18n/locales/tr.json
CHANGED
|
@@ -649,7 +649,9 @@
|
|
|
649
649
|
"serviceHint": "Tüm servis için programlama standartları. Seçilen her parçanın içeriği, bu servisin görevlerinde çalışan kod farkında her ajanın prompt'una eklenir.",
|
|
650
650
|
"serviceEmpty": "Yok. Bu servisteki kod farkında ajanlar varsayılan yönergelerini izler.",
|
|
651
651
|
"manageBoard": "Bu pano'nun fragman kütüphanesini yönet…",
|
|
652
|
-
"manageAccount": "Hesap fragmanlarını yönet…"
|
|
652
|
+
"manageAccount": "Hesap fragmanlarını yönet…",
|
|
653
|
+
"done": "Tamam",
|
|
654
|
+
"pickerEmpty": "Kullanılabilir parça yok."
|
|
653
655
|
},
|
|
654
656
|
"frontendConfig": {
|
|
655
657
|
"title": "Frontend",
|
package/i18n/locales/uk.json
CHANGED
|
@@ -649,7 +649,9 @@
|
|
|
649
649
|
"serviceHint": "Стандарти програмування для всього сервісу. Вміст кожного вибраного фрагмента додається до промпту кожного агента, що працює з кодом завдань цього сервісу.",
|
|
650
650
|
"serviceEmpty": "Немає. Агенти, що працюють з кодом цього сервісу, дотримуються типових інструкцій.",
|
|
651
651
|
"manageBoard": "Керувати бібліотекою фрагментів цієї дошки…",
|
|
652
|
-
"manageAccount": "Керувати фрагментами облікового запису…"
|
|
652
|
+
"manageAccount": "Керувати фрагментами облікового запису…",
|
|
653
|
+
"done": "Готово",
|
|
654
|
+
"pickerEmpty": "Немає доступних фрагментів."
|
|
653
655
|
},
|
|
654
656
|
"frontendConfig": {
|
|
655
657
|
"title": "Frontend",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/app",
|
|
3
|
-
"version": "0.146.
|
|
3
|
+
"version": "0.146.3",
|
|
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",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"valibot": "^1.4.2",
|
|
41
41
|
"vue": "3.5.40",
|
|
42
42
|
"wretch": "^3.0.9",
|
|
43
|
-
"@cat-factory/contracts": "0.
|
|
43
|
+
"@cat-factory/contracts": "0.153.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@toad-contracts/testing": "0.3.2",
|